utils.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import collections
  2. from django.db.models import Q
  3. from django.utils.deconstruct import deconstructible
  4. from taggit.managers import _TaggableManager
  5. from utilities.querysets import DummyQuerySet
  6. from extras.constants import EXTRAS_FEATURES
  7. from extras.registry import registry
  8. def is_taggable(obj):
  9. """
  10. Return True if the instance can have Tags assigned to it; False otherwise.
  11. """
  12. if hasattr(obj, 'tags'):
  13. if issubclass(obj.tags.__class__, _TaggableManager):
  14. return True
  15. # TaggableManager has been replaced with a DummyQuerySet prior to object deletion
  16. if isinstance(obj.tags, DummyQuerySet):
  17. return True
  18. return False
  19. def image_upload(instance, filename):
  20. """
  21. Return a path for uploading image attchments.
  22. """
  23. path = 'image-attachments/'
  24. # Rename the file to the provided name, if any. Attempt to preserve the file extension.
  25. extension = filename.rsplit('.')[-1].lower()
  26. if instance.name and extension in ['bmp', 'gif', 'jpeg', 'jpg', 'png']:
  27. filename = '.'.join([instance.name, extension])
  28. elif instance.name:
  29. filename = instance.name
  30. return '{}{}_{}_{}'.format(path, instance.content_type.name, instance.object_id, filename)
  31. @deconstructible
  32. class FeatureQuery:
  33. """
  34. Helper class that delays evaluation of the registry contents for the functionality store
  35. until it has been populated.
  36. """
  37. def __init__(self, feature):
  38. self.feature = feature
  39. def __call__(self):
  40. return self.get_query()
  41. def get_query(self):
  42. """
  43. Given an extras feature, return a Q object for content type lookup
  44. """
  45. query = Q()
  46. for app_label, models in registry['model_features'][self.feature].items():
  47. query |= Q(app_label=app_label, model__in=models)
  48. return query
  49. def extras_features(*features):
  50. """
  51. Decorator used to register extras provided features to a model
  52. """
  53. def wrapper(model_class):
  54. # Initialize the model_features store if not already defined
  55. if 'model_features' not in registry:
  56. registry['model_features'] = {
  57. f: collections.defaultdict(list) for f in EXTRAS_FEATURES
  58. }
  59. for feature in features:
  60. if feature in EXTRAS_FEATURES:
  61. app_label, model_name = model_class._meta.label_lower.split('.')
  62. registry['model_features'][feature][app_label].append(model_name)
  63. else:
  64. raise ValueError('{} is not a valid extras feature!'.format(feature))
  65. return model_class
  66. return wrapper