You are not logged in Log in Join
You are here: Home » Members » camil7 » Silva Documentation and HowTo's » archive for ancient content » Check the image size for custom content types

Log in
Name

Password

 

Check the image size for custom content types

Motivation

If You have a custom tailored layout for Your custom content type, which contains images, You maybe expect the image to have some certain size (in pixels), and want restrict the set of images available when editing the content.

I show a simple way to do this here. This involves the following steps:

  1. Define the filter within the content type definition on the file system level.
  2. Activate the filter within the edit view of the content type.
  3. Apply the filter within the rendering widget for the image tag.

Since Silva0.8.6 there has been a major rework, especially an export of all system specific views, widgets, etc. to the file system.
This HowTo does not wokr for any Silva with version number higher than 0.8.6.

The HowTo is defined by the example News content type the other HowTo's use, too. As this is not exactly the code I am using right now, some inconsistencies may have slipped in. Please tell me for I can fix them.

This HowTo is tested with Silva-0.8.3, though it should work with older versions.

Note: this will not work with Silva-0.8.6 and higher, as image selection has been reworked completely there.

Define the Filter

The filter is nothing but some python method I plan to feed to the filter function; i.e. it gets an image as one parameter and returns a true value, if the image is acceptable.

I personally prefer to define this in the file system level in the file the class of the content type is actually defined at. Arbitrarily I decided to implement it in the NewsVersion class within Custom/News.py.

*(skip on first reading) The method looks "nearly generic"; I guess You could define it in a general utils package and add a proxy method passing the image and the limits to the class or some smarter solution.*

    image_limits = [ (140,86,140,86) ]
 
    security.declareProtected(SilvaPermissions.ReadSilvaContent,
                              'image_check')
    def image_check(self, silva_image):
        " return true if the image may be added to this content "
        # filter out not yet existing images
        if not silva_image.image: return None
 
        # loop over all limits, bail out successfully on first match
        x, y = silva_image.image.width,  silva_image.image.height
        for x_lower, y_lower, x_upper, y_upper in self.image_limits:
            if (x_lower <= x <= x_upper)  and (y_lower <= y <= y_upper):
                return 1
        return None

The image_limits is a list of 4-tuples containing ranges of pixel sizes; images within the range are acceptable. If at least one limit is acceptable, the image is accepted.

Feel free to implement something different suiting to your needs. Note you can access the attribute image.content_type to check for different image formats if you want to.

The example limits allows only images of exactly 140 x 86 pixels.

Get the Filter into Use:

To use the filter I propose to pass the filtering method via a request attribute from the contents edit view to the XML Widget actually doing the rendering.

In template /silva/service_custom_view_registry/edit/VersionedContent/News/normal_edit change the image-editor tag.

<image-editor tal:omit-tag=""
                tal:define="dummy python:request.set('image_filter', editable.image_check)">
*Note: previous versions of the HowTo use the location /silva/service_view_registry/edit/VersionedContent/Custom/News/normal_edit which leads to a non smooth upgrade process in case of upgrading Silva.*

Apply the Filter

The display of the images to be added to the content type happens in the widget /silva/service_widgets/element/doc_elements/image/mode_edit/render (except You made a custom copy of the whole widget items.)

Here I propose to change the initialization line:

<tal:init tal:define="global assets python:node.get_container().get_assets_of_type('Silva Image')" />
to
<tal:init tal:define="
     image_filter python:getattr(request,'image_filter',None);
     global assets python:filter(image_filter, node.get_container().get_assets_of_type('Silva Image'))" />

(If You filter via None, nothing happens, e.g. the sequence passes through unchanged. Thus content types without limitations of the image size are not affected.)

This modification has the effect that images not passing the check do not show up in the list of images to be added. In the extreme case this could lead to a no images in this folder message although there are plenty of them albeit not fitting the restrictions of this content type. This might confuse the users.

The alternative is to show all images but only allow to add the ones passing the test. This could happen by defining two global lists:

 <tal:init tal:define="
     image_filter python:getattr(request,'image_filter',nothing);
     global assets python:node.get_container().get_assets_of_type('Silva Image');   
     global good_assets python:filter(image_filter,assets)
" />

and then below in the loop over all 'assets':

<input type="radio" name="image_id" value="id"
       tal:attributes="value python:asset.id; 
                       checked python:test(active, 'checked', None)" />
insert a test, if the image is in the list of suitable images:
<input type="radio" name="image_id" value="id"
       tal:condition="python:asset in good_assets"
       tal:attributes="value python:asset.id; 
                       checked python:test(active, 'checked', None)" />
<span tal:condition="python:not asset in good_assets"> </span>

This prevents adding images having the wrong size.

Remarks

  • The second implementation of applying the filter is somewhat inefficient, especially if there are lots of images. It is very easy to figure out how to do better, I guess, thus I decide I am allowed to be too lazy to include the improvement ;)
  • The second implementation leads to a rotten layout, as the icons for the images are rendered in a different position depending on if they may be added or not. Again this is easy to fix by putting the radio buttons into an own column.
  • You can restrict different images within the same content types by different filters - simply pass the filters within their image-editor tags. However if You want to have an unrestricted image after a restricted one, You first have to clear the request attribute from the previous image, as request attributes scope is not nested within the scope of the image-editor tag. You clear the filter by the following code snippet:
    <image-editor tal:omit-tag=""
                  tal:define="dummy python:request.set('image_filter', None)">
        
  • This image restriction is meant to support the authors in using images fitting into the design. It does not force them to do so. One can easy outsmart this filter by first uploading some suitable image, then adding this image to the content and later replace the suitable image by an image which does not fit in. I don't know if there is yet a way to prevent this to happen accidentally.

back to the index