2013-08-27 6 views
3

Я запускаю Plone 4.3 и пытаюсь создать собственный портлет. Портлет прост и должен позволить пользователю загружать изображение и предоставлять некоторый описательный текст, который может отображаться под изображением.Plone portlet using plone.namedfield.field.NamedImage

Вот код, который я до сих пор:

from zope.interface import implements 
from zope.formlib import form 
from zope import schema 
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile 
from plone.app.portlets.portlets import base 
from plone.memoize.instance import memoize 
from plone.namedfile.field import NamedImage 
from plone.directives import form 
from z3c.form import field 
from plone.app.portlets.browser import z3cformhelper 

class IMyImagePortlet(form.Schema): 

    myimagetitle = schema.TextLine(
     title=u"Image title", 
     description=u"Enter the image title", 
     default=u"", 
     required=True) 

    myimagedescription = schema.TextLine(
     title=u"Image text", 
     description=u"Enter the text which appears below the image", 
     default=u"", 
     required=True) 

    myimage = NamedImage(
     title=u"My image", 
     description=u"Upload an image", 
     required=True) 

class Assignment(base.Assignment): 
    implements(IMyImagePortlet) 

    header = u"My Image" 
    myimagetitle = u"" 
    myimagedescription = u"" 
    myimage = u"" 

    def __init__(self, myimagetitle=None, myimagedescription=None, myimage=None): 
     self.myimagetitle = myimagetitle 
     self.myimagedescription = myimagedescription 
     self.myimage = myimage 

    @property 
    def title(self): 
     """This property is used to give the title of the portlet in the 
     "manage portlets" screen. 
     """ 
     return u"My image" 

class Renderer(base.Renderer): 

    _template = ViewPageTemplateFile('templates/myimage_portlet.pt') 

    def __init__(self, *args): 
     base.Renderer.__init__(self, *args) 

    @memoize 
    def myimagetitle(self): 
     return self.data.myimgaetitle 

    @memoize 
    def myimagedescription(self): 
     return self.data.myimagedescription 

    @memoize 
    def myimage(self): 
     return self.data.myimage 

    def render(self): 
     return self._template() 

class AddForm(z3cformhelper.AddForm): 
    fields = field.Fields(IMyImagePortlet) 

    label = u"Edit image" 
    description = u"A portlet which can display image with text" 

    def create(self, data): 
     return Assignment(**data) 

class EditForm(z3cformhelper.EditForm): 
    fields = field.Fields(IMyImagePortlet) 

    label = u"Edit image" 
    description = u"A portlet which can display image with text" 

Это, кажется, работает, как ожидалось, и позволяет мне добавить новый портлет с названием, изображение и описание изображения. Тем не менее, я читал документы, и я не мог найти много примеров создания портлета с полем загрузки изображений, поэтому может быть лучший способ сделать это.

Моя проблема заключается в том, что я не могу изобразить изображение в шаблоне. Я со ссылкой на документы в https://developer.plone.org/reference_manuals/external/plone.app.dexterity/advanced/files-and-images.html и имею следующее в моем шаблоне, но не отображается изображение:

<div tal:define="picture nocall:context/myimage" 
    tal:condition="nocall:picture"> 
    <img tal:attributes="src string:${context/absolute_url}/@@download/myimage/${picture/filename}; 
        height picture/_height | nothing; 
        width picture/_width | nothing;" 
    /> 
</div> 
+0

Никакой определенный ответ не приходит в голову сразу, но я вижу, в чем проблема. Проблема в том, что поле изображения определено в портлете, но код шаблона пытается получить его из контекста, поэтому из элемента контента. Этот элемент содержимого не имеет поля myimage, поэтому условие tal: false является ошибочным и атрибут src тоже не работает. Вы можете начать с изменения «context/myimage» на «view/image» и посмотреть, сможете ли вы оттуда уйти. – maurits

+0

См. Пакет imageportlet на Github, решая именно эту проблему. –

+0

@MikkoOhtamaa. Я замечаю, что вы реализуете интерфейс ImageScaleTraversable в коде портлета. Есть ли у вас пример использования этой функции масштабирования в шаблоне? – manicminer

ответ

0

Мы сделали именно то, что вы хотите. https://github.com/4teamwork/ftw.subsite/tree/master/ftw/subsite/portlets Это портлет тизера, к сожалению, не в одном пакете. но вы можете адаптировать код к вашим потребностям.

Мы определили вид браузера в image.py:

from Acquisition import aq_inner 
from zope.publisher.browser import BrowserView 


class ImageView(BrowserView): 
    """View the image field of the image portlet. We steal header details 
    from zope.app.file.browser.file and adapt it to use the dublin 
    core implementation that the Image object here has.""" 

    def __call__(self): 
     context = aq_inner(self.context) 
     image = context.image 
     self.request.response.setHeader('Content-Type', image.contentType) 
     self.request.response.write(image.data) 

Регистрация с ZCML (Важно вид изображение является for ваш портлет Назначение):

<browser:page 
    for=".yourportlet.Assignment" 
    name="image" 
    class=".image.ImageView" 
    permission="zope.Public" 
/> 

В вашем портлета видеообработки вы должны определите метод, который получает изображение (траверс).

from plone.app.portlets.portlets import base 


class MyPortletRenderer(base.Renderer) 

    def image_tag(self): 
     state = getMultiAdapter((self.context, self.request), 
           name="plone_portal_state") 
     portal = state.portal() 
     assignment_url = \ 
      portal.unrestrictedTraverse(
      self.data.assignment_context_path).absolute_url() 

     return "<img src='%s/%s/@@image' alt=''/>" % (
      assignment_url, 
      self.data.__name__) 

Теперь вы можете использовать изображение в портлет:

<tal:image content="structure view/image_tag /> 

Я не знаю, если есть более простое решение. Именование может быть лучше :-) Но он работает, и он протестирован https://github.com/4teamwork/ftw.subsite/blob/master/ftw/subsite/tests/test_subsiteportlet.py