PageRenderTime 739ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Kommonz/apps/materials/models.py

https://github.com/kawazrepos/Kommonz
Python | 255 lines | 192 code | 21 blank | 42 comment | 10 complexity | 4bc916248db1bb7c220a18f25dd341c9 MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. #
  3. # Kommonz.apps.materials.models.base
  4. # created by giginet on 2011/10/02
  5. #
  6. import os
  7. import mimetypes
  8. from django.contrib.auth.models import User
  9. from django.conf import settings
  10. from django.core.files.storage import default_storage
  11. from django.db import models
  12. from django.db.models.fields.files import ImageFieldFile
  13. from django.db.models.signals import pre_delete
  14. from django.dispatch.dispatcher import receiver
  15. from django.utils.translation import ugettext as _
  16. from django.core.exceptions import ValidationError, ObjectDoesNotExist
  17. from qwert.middleware.threadlocals import request as get_request
  18. from apps.categories.models import Category
  19. from apps.licenses.models import License, CCLicense
  20. from apps.keros.models import Kero
  21. from fields.thumbnailfield.fields import ThumbnailField
  22. from managers import MaterialManager
  23. MATERIAL_FILE_PATH = os.path.join('storage', 'materials')
  24. DEFAULT_THUMBNAIL_PATH = os.path.join('image', 'default', 'material', '%s.png')
  25. class MaterialFile(models.Model):
  26. """
  27. A Model for material raw file.
  28. """
  29. def _get_file_path(self, filename):
  30. request = get_request()
  31. if not request:
  32. user = User.objects.get(pk=1)
  33. else:
  34. user = request.user
  35. path = os.path.join(MATERIAL_FILE_PATH, user.username, filename)
  36. path = default_storage.get_available_name(path) # dirname will not duplicate.
  37. return os.path.join(path, filename)
  38. file = models.FileField(_('File'), upload_to=_get_file_path)
  39. author = models.ForeignKey(User, verbose_name=_('author'), editable=False, related_name="materialfiles")
  40. class Meta:
  41. app_label = 'materials'
  42. ordering = ('-material__pk',)
  43. verbose_name = _('MaterialFile')
  44. verbose_name_plural = _('MaterialFiles')
  45. def save(self, *args, **kwargs):
  46. request = get_request()
  47. if request and request.user.is_authenticated():
  48. self.author = request.user
  49. else:
  50. self.author = User.objects.get(pk=1)
  51. super(MaterialFile, self).save(*args, **kwargs)
  52. def __unicode__(self):
  53. return self.file.name
  54. @property
  55. def extension(self):
  56. return os.path.splitext(self.file.name)[1][1:]
  57. class Material(models.Model):
  58. """
  59. A model for all materials.
  60. """
  61. THUMBNAIL_SIZE_PATTERNS = {
  62. 'huge': (288, 288, False),
  63. 'large': (144, 144, False),
  64. 'middle': (48, 48, False),
  65. 'small': (27, 27, False),
  66. }
  67. def _get_thumbnail_path(self, filename):
  68. path = os.path.dirname(self.file.name)
  69. name, ext = os.path.splitext(filename)
  70. thumbnail_name = default_storage.get_available_name('thumbnail%s' % ext)
  71. return os.path.join(path, 'thumbnails', thumbnail_name)
  72. # required
  73. label = models.CharField(_('Label'), max_length=128, null=False, blank=False)
  74. _file = models.OneToOneField(MaterialFile, verbose_name=('Material'), related_name='material')
  75. # not required
  76. description = models.TextField(_('Description'), blank=True, null=True)
  77. category = models.ForeignKey(Category, verbose_name=_('Category'), related_name='materials', blank=True, null=True)
  78. license = models.ForeignKey(License, verbose_name=_('License'), related_name='materials', blank=True, null=True)
  79. kero = models.ForeignKey(Kero, verbose_name=_('KERO'), related_name='materials', blank=True, null=True)
  80. # auto add
  81. created_at = models.DateTimeField(_('Created At'), auto_now_add=True)
  82. updated_at = models.DateTimeField(_('Updated At'), auto_now=True)
  83. author = models.ForeignKey(User, verbose_name=_('author'), editable=False, related_name="materials")
  84. pv = models.PositiveIntegerField(_('Page View'), default=0, editable=False)
  85. download = models.PositiveIntegerField(_('Download Count'), default=0, editable=False)
  86. ip = models.IPAddressField(_('IP Address'), editable=False)
  87. _thumbnail = ThumbnailField(_('Thumbnail'), upload_to=_get_thumbnail_path, thumbnail_size_patterns=THUMBNAIL_SIZE_PATTERNS, null=True, blank=True)
  88. objects = MaterialManager()
  89. license_type = CCLicense
  90. class Meta:
  91. app_label = 'materials'
  92. ordering = ('-created_at',)
  93. verbose_name = _('Material')
  94. verbose_name_plural = _('Materials')
  95. def __unicode__(self):
  96. return '%s(%s)' % (self.label, self.file.name)
  97. def clean(self):
  98. if not self.category:
  99. self.category = Category.objects.get_filetype_category(self.file.name)
  100. if self.license:
  101. try:
  102. self.license_type.objects.get(pk=self.license.pk)
  103. except ObjectDoesNotExist:
  104. raise ValidationError(_('''can not set the selected license with this model.'''))
  105. else:
  106. raise ValidationError(_('''you have to select license.'''))
  107. # or set default license
  108. return super(Material, self).clean()
  109. @models.permalink
  110. def get_absolute_url(self):
  111. return ('materials_material_detail', (), {'pk': self.pk})
  112. def _get_default_thumbnail_path(self):
  113. return DEFAULT_THUMBNAIL_PATH % self.filetype
  114. @property
  115. def thumbnail(self):
  116. """
  117. Returns thumbnail file to display.
  118. """
  119. return ThumbnailFile(self, self._thumbnail.field)
  120. @property
  121. def file(self):
  122. """
  123. Alias for MaterialFile.file
  124. """
  125. return self._file.file
  126. @property
  127. def mimetype(self):
  128. """
  129. Returns mimetype of own file
  130. Example : 'audio/wav'.
  131. """
  132. try:
  133. mimetypes.init()
  134. type = mimetypes.guess_type(self.file.name)[0]
  135. except:
  136. type = None
  137. return type
  138. @property
  139. def filetype(self):
  140. """
  141. Returns file type name like
  142. Example : 'audio'
  143. """
  144. from utils.filetypes import guess
  145. return guess(self.file.name)
  146. @property
  147. def size(self):
  148. """
  149. Returns filesize(byte).
  150. """
  151. try:
  152. return self.file.size
  153. except:
  154. return 0
  155. @property
  156. def model(self):
  157. """
  158. Returns it's model class.
  159. """
  160. from utils.filetypes import get_file_model
  161. return get_file_model(self.file.name)
  162. @property
  163. def extension(self):
  164. """
  165. Returns extension of own file.
  166. It may not be include '.' and casted to lower case.
  167. hoge.png #=> png
  168. hoge.MP3 #=> mp3
  169. """
  170. return os.path.splitext(self.file.name)[1][1:].lower()
  171. @property
  172. def filename(self):
  173. """
  174. Returns filename of own file.
  175. """
  176. return os.path.basename(self.file.name)
  177. def save(self, *args, **kwargs):
  178. from utils.filetypes import get_file_model
  179. cls = get_file_model(self.label)
  180. if not isinstance(self, cls):
  181. extended = cls(pk=self.pk)
  182. extended.__dict__.update(self.__dict__)
  183. extended.save()
  184. request = get_request()
  185. if not self.label:
  186. self.label = self.file.name
  187. if request and request.user.is_authenticated():
  188. self.author = request.user
  189. self.ip = request.META['REMOTE_ADDR']
  190. else:
  191. self.author = User.objects.get(pk=1)
  192. self.ip = "0.0.0.0"
  193. if not self.category:
  194. self.category = Category.objects.get_filetype_category(self.file.name)
  195. return super(Material, self).save(*args, **kwargs)
  196. def modify_object_permission(self, mediator, created):
  197. mediator.manager(self, self.author)
  198. mediator.viewer(self, None)
  199. mediator.viewer(self, 'anonymous')
  200. @receiver(pre_delete, sender=Material)
  201. def delete_material_file(sender, instance, **kwargs):
  202. import shutil
  203. if os.path.exists(os.path.dirname(instance.file.path)):
  204. shutil.rmtree(os.path.dirname(instance.file.path))
  205. class ThumbnailFile(ImageFieldFile):
  206. """
  207. Thumbnail Image class.
  208. """
  209. def __init__(self, instance, field):
  210. if instance._thumbnail:
  211. self.thumbnail = instance._thumbnail.name
  212. else:
  213. self.thumbnail = instance._get_default_thumbnail_path()
  214. super(ImageFieldFile, self).__init__(instance, field, self.thumbnail)
  215. for pattern_name, pattern_size in Material.THUMBNAIL_SIZE_PATTERNS.iteritems():
  216. path, ext = os.path.splitext(self.thumbnail)
  217. if os.path.exists(os.path.join(settings.MEDIA_ROOT, "%s.%s%s" % (path, pattern_name, ext))):
  218. setattr(self, pattern_name, ImageFieldFile(instance, field, "%s.%s%s" % (path, pattern_name, ext)))