Skip to main content
🐍⚡️Support Python for everyone by grabbing a 30% discount on PyCharm—ALL proceeds go to the Python Software Foundation. Offer ends soon, so grab it today!  GET 30% OFF PYCHARM

Image widget (with thumbnails) for z3c.form, using Grok

Project description

dolmen.widget.image is a thin layer above dolmen.widget.file providing a widget suitable to fields implementing IImageField. It adds, thanks to dolmen.thumbnailer a preview of the uploaded image in both input and display mode.

Example

We are going to develop here a small example, to demonstrate the use of dolmen.widget.image. First, we instanciate our test model and add an image field to the object:

>>> from persistent import Persistent

>>> class Mammoth(Persistent):
...     pass

>>> import dolmen.file
>>> import grokcore.component as grok
>>> from zope.interface import Interface, alsoProvides
>>> from zope.schema.fieldproperty import FieldProperty

>>> class IMammothId(Interface):
...   """Even mammoths need an ID card"""
...   picture = dolmen.file.ImageField(title=u'Luggages')

>>> manfred = Mammoth()
>>> manfred.picture = None
>>> alsoProvides(manfred, IMammothId)

The picture is now set on our Mammoth. We create a form to try and edit the picture field:

>>> from megrok.z3cform.base import EditForm

>>> class EditMammoth(EditForm):
...    grok.name('edit')
...    grok.context(IMammothId)

>>> grok.testing.grok_component('edit', EditMammoth)
True

We persist our Mammoth to get a located mammoth with an URL:

>>> from zope.component.hooks import getSite
>>> root = getSite()
>>> root['manfred'] = manfred
>>> manfred = root['manfred']

We can call the edit form on our persisted object:

>>> from zope.component import getMultiAdapter
>>> from zope.publisher.browser import TestRequest

>>> request = TestRequest()

>>> form = getMultiAdapter((manfred, request), name='edit')
>>> form.updateWidgets()
>>> print form.widgets['picture'].render()
<div id="form-widgets-picture"
     class="image-widget required imagefield-field">
  <input type="file" id="form-widgets-picture-input"
         name="form.widgets.picture" />
</div>

Now, let’s try with a fake value:

>>> manfred.picture = "some fake image"
>>> form = getMultiAdapter((manfred, request), name='edit')
>>> form.updateWidgets()

>>> print form.widgets['picture'].render()
<div id="form-widgets-picture"
     class="image-widget required imagefield-field">
  <div class="image-widget-preview">
    <img src="http://127.0.0.1/manfred/++thumbnail++picture.preview" />
  </div>
  <span>
    <a href="http://127.0.0.1/manfred/++download++picture"></a> &mdash;
  </span>
  <div style="padding-top: 1em;">
    <input type="radio" value="nochange" checked="checked"
           class="noborder"
           name="form.widgets.picture.nochange"
           onclick="document.getElementById('form-widgets-picture-input').disabled=true"
           id="form-widgets-picture-nochange" />
<BLANKLINE>
    <label for="form-widgets-picture-nochange">Keep existing file</label>
    <br />
    <input type="radio" value="delete" class="noborder"
           name="form.widgets.picture.nochange"
           onclick="document.getElementById('form-widgets-picture-input').disabled=true"
           id="form-widgets-picture-delete" />
    <label for="form-widgets-picture-delete">Delete existing file</label>
    <br />
    <input type="radio" name="form.widgets.picture.nochange"
           onclick="document.getElementById('form-widgets-picture-input').disabled=false"
           id="form-widgets-picture-replace" />
    <label for="form-widgets-picture-replace">Replace with new file</label>
  </div>
  <input type="file" id="form-widgets-picture-input"
         name="form.widgets.picture" />
<BLANKLINE>
  <script type="text/javascript">document.getElementById('form-widgets-picture-input').disabled=true;</script>
</div>
<BLANKLINE>

With non persistent objects (which don’t resolve to an URL), no preview is displayed. If we can’t resolve to an URL, we can’t serve the thumbnail or download the data:

>>> judith = Mammoth()
>>> judith.picture = "Fake image data"
>>> alsoProvides(judith, IMammothId)

>>> form = getMultiAdapter((judith, request), name='edit')
>>> form.updateWidgets()
>>> print form.widgets['picture'].render()
<div id="form-widgets-picture"
     class="image-widget required imagefield-field">
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
<BLANKLINE>
  <div style="padding-top: 1em;">
    <input type="radio" value="nochange" checked="checked"
           class="noborder"
           name="form.widgets.picture.nochange"
           onclick="document.getElementById('form-widgets-picture-input').disabled=true"
           id="form-widgets-picture-nochange" />
<BLANKLINE>
    <label for="form-widgets-picture-nochange">Keep existing file</label>
    <br />
<BLANKLINE>
    <label for="form-widgets-picture-delete">Delete existing file</label>
    <br />
    <input type="radio" name="form.widgets.picture.nochange"
           onclick="document.getElementById('form-widgets-picture-input').disabled=false"
           id="form-widgets-picture-replace" />
    <label for="form-widgets-picture-replace">Replace with new file</label>
  </div>
  <input type="file" id="form-widgets-picture-input"
         name="form.widgets.picture" />
<BLANKLINE>
  <script type="text/javascript">document.getElementById('form-widgets-picture-input').disabled=true;</script>
</div>
<BLANKLINE>

Changelog

0.2 (2010-03-01)

  • Updated the code to use dolmen.widget.file 0.2 and dolmen.file 0.5.1.

  • Updated the template to use the zope.size.ISized adapter to display the file size.

  • Updated the tests to get rid of the unneeded zope.app packages.

0.1 (2009-10-22)

  • Initial release

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page