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

Tracking PR - A conversation starter #10

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Tracking PR - A conversation starter #10

wants to merge 1 commit into from

Conversation

sergiosoria
Copy link

Our issue: We have many use cases for a given image uploaded into our system. Each use case requires an image of a specific size/aspect ratio. While we could handle the size issue by always sending the largest version of the image and allowing the browser to scale the image down, we'd still suffer from image distortion when the use case requires a change to the aspect ratio. So, at the very least, we would need to create a crop of each image for each unique aspect ratio that exists on our site. Cropping automatically is unreliable (from a quality perspective) so, our users would still need the ability to override a bad crop.

Our Solution: Create simple way, in the Django admin, for users to create a custom crop for each image use case.

Implementation: This feature comes in two parts: a custom django DB field and a custom django form widget.

The DB field maintains the crop (use case) definitions, creates the various image version (by cropping and resizing), and provides a simple way to access image versions from the fieldFile instance returned when image field is accessed.

The form widget handles the creation of the cropper (in the admin) and some of the user input validation. Here is a shot of it in action:

cropper-ex

This implementation relies on user provided functions and Django storages to define how to access each image version (just like ImageField does with it's 'upload_to' parameter); so, no additional information is written to the database. A dictionary with accessor methods is added to the standard ImageFieldFile instance which allows access to image versions like this:

'field_name'.versions.'version_name'

Code clean up and tests are forthcoming. In the mean time, I'd like to hear your comments/concerns regarding this feature. Is apps.images the place for this kind of thing? If not, where does it belong?


# attach debug information
field_file_object.actual_path = filepath
field_file_object.missing_file = True
Copy link
Member

Choose a reason for hiding this comment

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

This block isn't strictly necessary—we can refactor and discuss—but it's been useful in two commons cases. In debug mode when the image can't be found, this substitutes a (in our case) 1 pixel gray image and attaches the path of the intended-but-missing file along with a flag. The template (we have a single shared generic image display template) uses the defined version dimensions to set the height and width <img> attributes resulting in a placeholder grey box appearing exactly how the real image would appear and thus not breaking layouts. A little JavaScript warns in the console.

{% if file.missing_file %}
  <script>window.console && console.warn("broken image: {{ file.actual_path }}");</script>
{% endif %}

This has been really helpful when running on a development database (incorrect image paths), when using a development S3 bucket (no actual images) and when working without Internet (like on a train). We also use a USE_REMOTE_FILE_STORAGE setting for "train development" that short circuits having to wait for the self.field.storage.exists() timeout.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants