user_media.models: 45 total statements, 100.0% covered

Generated: Mon 2014-08-04 18:55 CEST

Source file: /home/tobi/Projects/django-user-media/src/user_media/models.py

Stats: 35 executed, 0 missed, 10 excluded, 96 ignored

  1. """Models for the ``django-user-media`` app."""
  2. import glob
  3. import os
  4. import uuid
  5. from django.conf import settings
  6. from django.contrib.contenttypes import generic
  7. from django.contrib.contenttypes.models import ContentType
  8. from django.db import models
  9. from django.db.models.signals import post_delete
  10. from django.dispatch import receiver
  11. from django.utils.translation import ugettext_lazy as _
  12. def get_image_file_path(instance, filename):
  13. """Returns a unique filename for images."""
  14. ext = filename.split('.')[-1]
  15. filename = '%s.%s' % (uuid.uuid4(), ext)
  16. return os.path.join(
  17. 'user_media', str(instance.user.pk), 'images', filename)
  18. class UserMediaImage(models.Model):
  19. """
  20. An image that can be uploaded by a user.
  21. If the image belongs to a certain object that is owned by the user, it
  22. can be tied to that object using the generic foreign key. That object
  23. must have a foreign key to ``auth.User`` (or another user model) and that
  24. field must be called ``user``.
  25. :user: The user this image belongs to.
  26. :content_type: If this image belongs to a certain object (i.e. a Vehicle),
  27. this should be the object's ContentType.
  28. :object_id: If this image belongs to a certain object (i.e. a Vehicle),
  29. this should be the object's ID.
  30. :image: The uploaded image.
  31. :position: The position of the image in case of multiple ones.
  32. :thumb_x: Thumbnail starting point on the x-axis.
  33. :thumb_x2: Thumbnail ending point on the x-axis.
  34. :thumb_y: Thumbnail starting point on the y-axis.
  35. :thumb_y2: Thumbnail ending point on the y-axis.
  36. :thumb_w: Thumbnail width.
  37. :thumb_h: Thumbnail height.
  38. """
  39. user = models.ForeignKey(
  40. getattr(settings, 'AUTH_USER_MODEL', 'auth.User'),
  41. verbose_name=_('User'),
  42. )
  43. content_type = models.ForeignKey(
  44. ContentType,
  45. null=True, blank=True,
  46. )
  47. object_id = models.PositiveIntegerField(
  48. null=True, blank=True
  49. )
  50. content_object = generic.GenericForeignKey('content_type', 'object_id')
  51. image = models.ImageField(
  52. upload_to=get_image_file_path,
  53. null=True, blank=True,
  54. verbose_name=_('Image'),
  55. )
  56. generic_position = generic.GenericRelation(
  57. 'generic_positions.ObjectPosition'
  58. )
  59. thumb_x = models.PositiveIntegerField(
  60. verbose_name=_('Thumbnail x'),
  61. null=True, blank=True,
  62. )
  63. thumb_x2 = models.PositiveIntegerField(
  64. verbose_name=_('Thumbnail x2'),
  65. null=True, blank=True,
  66. )
  67. thumb_y = models.PositiveIntegerField(
  68. verbose_name=_('Thumbnail y'),
  69. null=True, blank=True,
  70. )
  71. thumb_y2 = models.PositiveIntegerField(
  72. verbose_name=_('Thumbnail y2'),
  73. null=True, blank=True,
  74. )
  75. thumb_w = models.PositiveIntegerField(
  76. verbose_name=_('Thumbnail width'),
  77. null=True, blank=True,
  78. )
  79. thumb_h = models.PositiveIntegerField(
  80. verbose_name=_('Thumbnail height'),
  81. null=True, blank=True,
  82. )
  83. @property
  84. def box_coordinates(self):
  85. """Returns a thumbnail's coordinates."""
  86. if self.thumb_x and self.thumb_y and self.thumb_x2 and self.thumb_y2:
  87. return (
  88. int(self.thumb_x),
  89. int(self.thumb_y),
  90. int(self.thumb_x2),
  91. int(self.thumb_y2),
  92. )
  93. return False
  94. def large_size(self, as_string=True):
  95. """Returns a thumbnail's large size."""
  96. size = getattr(settings, 'USER_MEDIA_THUMB_SIZE_LARGE', (150, 150))
  97. if as_string:
  98. return u'{}x{}'.format(size[0], size[1])
  99. return size
  100. def small_size(self, as_string=True):
  101. """Returns a thumbnail's small size."""
  102. size = getattr(settings, 'USER_MEDIA_THUMB_SIZE_SMALL', (95, 95))
  103. if as_string:
  104. return u'{}x{}'.format(size[0], size[1])
  105. return size
  106. @receiver(post_delete, sender=UserMediaImage)
  107. def image_post_delete_handler(sender, instance, **kwargs):
  108. """
  109. Makes sure that a an image is also deleted from the media directory.
  110. This should prevent a load of "dead" image files on disc.
  111. """
  112. for f in glob.glob('{}/{}*'.format(instance.image.storage.location,
  113. instance.image.name)):
  114. if not os.path.isdir(f):
  115. instance.image.storage.delete(f)