utils.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. # Helper functions for migrating the Rendition.filter foreign key to the filter_spec field,
  2. # and the corresponding reverse migration
  3. def get_fill_filter_spec_migrations(app_name, rendition_model_name):
  4. def fill_filter_spec_forward(apps, schema_editor):
  5. # Populate Rendition.filter_spec with the spec string of the corresponding Filter object
  6. Rendition = apps.get_model(app_name, rendition_model_name)
  7. Filter = apps.get_model('wagtailimages', 'Filter')
  8. db_alias = schema_editor.connection.alias
  9. for flt in Filter.objects.using(db_alias):
  10. renditions = Rendition.objects.using(db_alias).filter(filter=flt, filter_spec='')
  11. renditions.update(filter_spec=flt.spec)
  12. def fill_filter_spec_reverse(apps, schema_editor):
  13. # Populate the Rendition.filter field with Filter objects that match the spec in the
  14. # Rendition's filter_spec field
  15. Rendition = apps.get_model(app_name, rendition_model_name)
  16. Filter = apps.get_model('wagtailimages', 'Filter')
  17. db_alias = schema_editor.connection.alias
  18. while True:
  19. # repeat this process until we've confirmed that no remaining renditions exist with
  20. # a null 'filter' field - this minimises the possibility of new ones being inserted
  21. # by active server processes while the query is in progress
  22. # Find all distinct filter_spec strings used by renditions with a null 'filter' field
  23. unmatched_filter_specs = Rendition.objects.using(db_alias).filter(
  24. filter__isnull=True).values_list('filter_spec', flat=True).distinct()
  25. if not unmatched_filter_specs:
  26. break
  27. for filter_spec in unmatched_filter_specs:
  28. filter, _ = Filter.objects.using(db_alias).get_or_create(spec=filter_spec)
  29. Rendition.objects.using(db_alias).filter(filter_spec=filter_spec).update(filter=filter)
  30. return (fill_filter_spec_forward, fill_filter_spec_reverse)
  31. def parse_color_string(color_string):
  32. """
  33. Parses a string a user typed into a tuple of 3 integers representing the
  34. red, green and blue channels respectively.
  35. May raise a ValueError if the string cannot be parsed.
  36. The colour string must be a CSS 3 or 6 digit hex code without the '#' prefix.
  37. """
  38. if len(color_string) == 3:
  39. r = int(color_string[0], 16) * 17
  40. g = int(color_string[1], 16) * 17
  41. b = int(color_string[2], 16) * 17
  42. elif len(color_string) == 6:
  43. r = int(color_string[0:2], 16)
  44. g = int(color_string[2:4], 16)
  45. b = int(color_string[4:6], 16)
  46. else:
  47. ValueError('Color string must be either 3 or 6 hexadecimal digits long')
  48. return r, g, b