Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change file/image field serializers to return a dict with additional metadata #115

Merged
merged 7 commits into from
May 29, 2016

Conversation

lukasgraf
Copy link
Member

@lukasgraf lukasgraf commented May 26, 2016

The Archetypes part of this needs a thorough review, I was struggling slightly with the different File / Image field type's APIs.


This changes the serialization format for file and image fields from returning a simple string to returning dictionaries that contain the download URL in a download key, according to #9 and #10.

There's also a change in behavior regarding empty file / image fields: Previously, those were still serialized to an URL that would have returned a 404 (or 500, not exactly sure). Now they'll be serialized to None.

RelationValue to a NamedBlobFile field

url = u'http://nohost/plone/doc1/@@download/testFileField'
self.assertEqual(
{u'filename': '',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part confused me - I wasn't able to set a filename for an atapi.FileField for the life of me. Does this field type actually support filenames? I wasn't able to find a clear reference for or against that. @buchi you probably know this.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To set the filename, you need to do (also works for AT blob fields):

file.getField('file').get(file).setFilename('newname.txt')

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erral thank you, that works. Though after looking at it again, it also seems to work for that field type by passing a keyword argument to the mutator - which I somehow couldn't get to work at first for that field type.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've been hit several times by the filenames (specially when running large imports), I think it's a bit obscure 😉

@lukasgraf lukasgraf mentioned this pull request May 26, 2016
3 tasks
@tisto
Copy link
Sponsor Member

tisto commented May 26, 2016

@lukasgraf Awesome!!! I will make a release as soon as this pr has been merged!

@buchi
Copy link
Member

buchi commented May 27, 2016

I strongly recommend to include the image dimensions in the output. Without the dimensions it's not possible to render "good" image tags.

See also Google Page Speed Guide: "If no dimensions are specified in the containing document, or if the dimensions specified don't match those of the actual images, the browser will require a reflow and repaint once the images are downloaded. To prevent reflows, specify the width and height of all images, either in the HTML tag, or in CSS."

"thumb": "http://localhost:55001/plone/image/@@images/image/thumb",
"tile": "http://localhost:55001/plone/image/@@images/image/tile"
"content-type": "image/png",
"download": "http://localhost:55001/plone/image/@@images/image",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would only include either the "download" or the "original" link, because both point to the same url.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll drop the original scale.

@lukasgraf
Copy link
Member Author

Ok, I'll update the PR to also include image dimensions with the scales.

@tisto
Copy link
Sponsor Member

tisto commented May 27, 2016

@buchi +1 for including the image dimensions. I had the same feeling, but did not want to complain before looking into it. :)

As soon as we have framing in place we can minimize the output if we need to...

@lukasgraf
Copy link
Member Author

@buchi @tisto updated:

  • Also got setting filename for atapi.FileField via mutator kwargs to work, simplified mutator call (always pass kwargs) (squashed)
  • Dropped original scale from list of scales (squashed)
  • Included dimensions in image scales, updated docs & JSON dumps accordingly
  • Factored out the scale / imaging related helper functions into plone.restapi.imaging, since duplication got out of hand

result = {
'filename': self.field.getFilename(self.context),
'content-type': self.field.getContentType(self.context),
'size': self.field .get_size(self.context),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnecessary space after self.field

@buchi
Copy link
Member

buchi commented May 27, 2016

The returned image dimensions should be the real dimensions of the scaled image and not the scales defined in image scaling. E.g. when scaling an image of size 500 x 400 to an image scale of 200 x 200 the resulting image will have the size 200 x 160, not 200 x 200 because the scaling is maintaining aspect ratio.

@lukasgraf
Copy link
Member Author

@buchi good point, I'll look into this.

@lukasgraf
Copy link
Member Author

@buchi @tisto updated:

  • Included the original image's width and height as top-level attributes
  • Return the actual dimensions of the scales (maintaining aspect ratio)
  • Updated docs and JSON dumps
  • Used a test image closer to real life in tests to demonstrate aspect ratio handling
  • Fixed unnecessary spaces

Using the @@images ImageScaling implementations for getting at the actual scale
dimensions would in theory be possible, but has some downsides:

  • Accessing a scale might trigger on-demand rendering, killing performance and possibly causing writes on GET.

    I haven't had the time to definitely confirm this, but depending on what ImageScaling implementation is being used, accessing a scale might not be free of side-effects.

  • Different ImageScale implementations seem to have slightly different APIs, and while a first attempt at using it seemed to work, getting a clean, abstracted solution for the different field types, Archetypes vs. Dexterity and Plone 4 vs 5 turned out to be non-trivial.

I briefly discussed this with @buchi, and I went with a solution that basically just applies the aspect ratio of the original image to the scale's (usually square) bounding box, which should result in the final scaled image's actual dimensions.

There's a couple boundary conditions to handle, but nothing too major:

  • How to deal with fractional pixel dimensions - truncate or round. Plone seems to truncate, so I did the same.
  • Don't produce dimensions with zero pixels on one side as a result of integer truncation
  • How to deal with scales that exceed the original image's dimensions:
    For the default named image scales, Plone doesn't upscale images, it just returns the image in it's original dimensions. We do the same.

"..." : {}
}

(For non-square images, those will be the actual scaled images' dimensions,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would simply drop this remark because maintaining aspect ratio is not related to square or non-square images. One could also define non-square image sizes (e.g. 600 x 400).

@lukasgraf
Copy link
Member Author

@buchi updated

@buchi buchi merged commit fb77e42 into master May 29, 2016
@buchi buchi deleted the file-image-download branch May 29, 2016 13:22
@tisto tisto removed the in progress label May 29, 2016
@tisto
Copy link
Sponsor Member

tisto commented May 29, 2016

Wohoo! I will go over the docs one last time and do some final checks and then make a first alpha release!

This was referenced May 29, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants