Refactor: remove Filter as a Django model.

This commit is contained in:
Gagaro 2016-04-28 14:43:56 +02:00 committed by Tim Heap
parent e995bc0e19
commit 4d7bdfd160
7 changed files with 74 additions and 13 deletions

View file

@ -11,6 +11,7 @@ Changelog
* `FieldRowPanel` now creates equal-width columns automatically if `col*` classnames are not specified (Chris Rogers)
* Form builder now validates against multiple fields with the same name (Richard McMillan)
* The 'choices' field on the form builder no longer has a maximum length (Johannes Spielmann)
* The wagtailimages.Filter model has been removed, and converted to a Python class instead (Gagaro)
* Fix: Email templates and document uploader now support custom `STATICFILES_STORAGE` (Jonny Scholes)
* Fix: Removed alignment options (deprecated in HTML and not rendered by Wagtail) from `TableBlock` context menu (Moritz Pfeiffer)
* Fix: Fixed incorrect CSS path on ModelAdmin's "choose a parent page" view
@ -21,7 +22,6 @@ Changelog
* Fixed regression in 1.5.1 on editing external links (Stephen Rice)
1.5.1 (07.06.2016)
~~~~~~~~~~~~~~~~~~

View file

@ -21,6 +21,7 @@ Minor features
* ``FieldRowPanel`` now creates equal-width columns automatically if ``col*`` classnames are not specified (Chris Rogers)
* Form builder now validates against multiple fields with the same name (Richard McMillan)
* The 'choices' field on the form builder no longer has a maximum length (Johannes Spielmann)
* The wagtailimages.Filter model has been removed, and converted to a Python class instead (Gagaro)
Bug fixes
@ -39,3 +40,8 @@ Form builder ``FormField`` models require a migration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``choices`` field on the ``wagtailforms.models.AbstractFormField`` model has been changed from a ``CharField`` to a ``TextField``, to allow it to be of unlimited length. If you are using the ``wagtailforms`` module in your project, you will need to run ``python manage.py makemigrations`` and ``python manage.py migrate`` after upgrading, in order to apply this change to your form page models.
``wagtailimages.Filter`` model has been removed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``wagtailimages.Filter`` model has been removed, and replaced with a ``Filter`` class instead. This class can be imported from the same location as the model: ``wagtail.wagtailimages.models.Filter``. The ``Filter`` class has the same API as the ``Filter`` model did, with the exception that Model methods such as ``Filter.save()``, and ``Filter.objects.get()`` have been removed.

View file

@ -74,8 +74,7 @@ class ThumbnailMixin(object):
'class': self.thumb_classname,
}
if image:
fltr, _ = Filter.objects.get_or_create(
spec=self.thumb_image_filter_spec)
fltr = Filter(spec=self.thumb_image_filter_spec)
img_attrs.update({'src': image.get_rendition(fltr).url})
return mark_safe('<img{}>'.format(flatatt(img_attrs)))
elif self.thumb_default:

View file

@ -872,7 +872,7 @@ class InspectView(InstanceSpecificView):
""" Render an image """
image = getattr(self.instance, field_name)
if image:
fltr, _ = Filter.objects.get_or_create(spec='max-400x400')
fltr = Filter(spec='max-400x400')
rendition = image.get_rendition(fltr)
return rendition.img_tag
return self.model_admin.get_empty_value_display(field_name)

View file

@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
def forwards_data_migration(apps, schema_editor):
Rendition = apps.get_model('wagtailimages', 'Rendition')
db_alias = schema_editor.connection.alias
# update doesn't work during migration, we have to do it one by one
for rendition in Rendition.objects.using(db_alias).select_related('filter').all():
rendition.filter2 = rendition.filter.spec
rendition.save()
def reverse_data_migration(apps, schema_editor):
Rendition = apps.get_model('wagtailimages', 'Rendition')
Filter = apps.get_model('wagtailimages', 'Filter')
db_alias = schema_editor.connection.alias
renditions = Rendition.objects.using(db_alias).all()
for rendition in renditions:
# Ensure we don't create the same Filter twice
rendition.filter, _ = Filter.objects.get_or_create(spec=rendition.filter2)
rendition.save()
class Migration(migrations.Migration):
dependencies = [
('wagtailimages', '0013_make_rendition_upload_callable'),
]
operations = [
# We create a new attribute to allow the data migration (filter -> filter2).
migrations.AddField(
model_name='Rendition',
name='filter2',
field=models.CharField(max_length=255, default=''),
preserve_default=False,
),
# Allow NULL for backward operation to work (no temporary default value possible as the `spec` attribute is not null but also unique).
migrations.AlterField('rendition', 'filter', models.ForeignKey(on_delete=models.CASCADE, related_name='+', to='wagtailimages.Filter', null=True)),
# Remove unique constraint to allow the removal of `filter` field.
migrations.AlterUniqueTogether('rendition', set([])),
# Migrate data.
migrations.RunPython(forwards_data_migration, reverse_data_migration),
# We can now delete Filter for good.
migrations.RemoveField(model_name='Rendition', name='filter'),
migrations.DeleteModel('Filter'),
# And we can finally set the new attribute as `filter`.
migrations.RenameField(model_name='Rendition', old_name='filter2', new_name='filter'),
# Bug with mysql and postgresql, we need to add the index after the renaming (https://code.djangoproject.com/ticket/25530).
migrations.AlterField('rendition', 'filter', models.CharField(max_length=255, db_index=True)),
# We can now set back the unique constraint.
migrations.AlterUniqueTogether('rendition', set([('image', 'filter', 'focal_point_key')])),
]

View file

@ -251,14 +251,14 @@ class AbstractImage(CollectionMember, TagSearchable):
def get_rendition(self, filter):
if isinstance(filter, string_types):
filter, created = Filter.objects.get_or_create(spec=filter)
filter = Filter(spec=filter)
cache_key = filter.get_cache_key(self)
Rendition = self.get_rendition_model()
try:
rendition = self.renditions.get(
filter=filter,
filter=filter.spec,
focal_point_key=cache_key,
)
except Rendition.DoesNotExist:
@ -285,7 +285,7 @@ class AbstractImage(CollectionMember, TagSearchable):
output_filename = output_filename_without_extension + '.' + output_extension
rendition, created = self.renditions.get_or_create(
filter=filter,
filter=filter.spec,
focal_point_key=cache_key,
defaults={'file': File(generated_image.f, name=output_filename)}
)
@ -367,15 +367,16 @@ def get_image_model():
return image_model
class Filter(models.Model):
class Filter(object):
"""
Represents one or more operations that can be applied to an Image to produce a rendition
appropriate for final display on the website. Usually this would be a resize operation,
but could potentially involve colour processing, etc.
"""
# The spec pattern is operation1-var1-var2|operation2-var1
spec = models.CharField(max_length=255, unique=True)
def __init__(self, spec):
# The spec pattern is operation1-var1-var2|operation2-var1
self.spec = spec
@cached_property
def operations(self):
@ -455,7 +456,7 @@ class Filter(models.Model):
class AbstractRendition(models.Model):
filter = models.ForeignKey(Filter, related_name='+')
filter = models.CharField(max_length=255, db_index=True)
file = models.ImageField(upload_to=get_rendition_upload_to, width_field='width', height_field='height')
width = models.IntegerField(editable=False)
height = models.IntegerField(editable=False)

View file

@ -74,8 +74,7 @@ class ImageNode(template.Node):
@cached_property
def filter(self):
_filter, _ = Filter.objects.get_or_create(spec=self.filter_spec)
return _filter
return Filter(spec=self.filter_spec)
def render(self, context):
try: