Changeset 129
- Timestamp:
- 02/06/10 23:32:29 (6 months ago)
- Location:
- trunk/courant/core/media
- Files:
-
- 2 modified
Legend:
- Unmodified
- Added
- Removed
-
trunk/courant/core/media/admin.py
r128 r129 34 34 }), 35 35 ) 36 36 37 37 inlines = [ 38 38 MediaBylineInline, … … 47 47 }), 48 48 ("Image", { 49 'fields': ('image',) 49 'fields': ('image',) 50 50 }), 51 51 ("Tags", { … … 66 66 }), 67 67 ("Details", { 68 'fields': ('url','image') 68 'fields': ('url','image') 69 69 }), 70 70 ("Tags", { … … 85 85 }), 86 86 ("Details", { 87 'fields': ('file',) 87 'fields': ('file',) 88 88 }), 89 89 ("Tags", { … … 102 102 raw_id_fields = ('media_item',) 103 103 fk_name = 'gallery' 104 104 105 105 class GalleryAdmin(MediaAdmin): 106 106 list_filter = ['created_at'] … … 111 111 admin.site.register(Gallery, GalleryAdmin) 112 112 113 class GalleryUploadAdmin(admin.ModelAdmin): 114 raw_id_fields = ('staffer',) 115 def has_change_permission(self, request, obj=None): 116 return False # To remove the 'Save and continue editing' button 117 admin.site.register(GalleryUpload, GalleryUploadAdmin) 118 119 113 120 class FileAdmin(MediaAdmin): 114 121 list_filter = ['created_at'] … … 118 125 }), 119 126 ("File", { 120 'fields': ('file','image','width','height') 127 'fields': ('file','image','width','height') 121 128 }), 122 129 ("Tags", { -
trunk/courant/core/media/models.py
r128 r129 4 4 from django.conf import settings 5 5 from django.core.cache import cache 6 from django.template.defaultfilters import slugify 7 from django.core.files.base import ContentFile 6 8 7 9 from courant.core.staff.models import Staffer, ContentByline … … 15 17 from django_extensions.db.fields import CreationDateTimeField, ModificationDateTimeField 16 18 17 from courant.core.media.utils import get_file_path, get_storage_path, get_image_path 19 from courant.core.media.utils import get_file_path, get_storage_path, get_image_path, get_temp_file_path 18 20 19 21 from sorl.thumbnail.main import DjangoThumbnail … … 24 26 import urllib 25 27 import os 28 import zipfile 29 30 try: 31 import Image 32 except ImportError: 33 try: 34 from PIL import Image 35 except ImportError: 36 raise ImportError('Courant was unable to import the Python Imaging Library. Please confirm it`s installed and available on your current Python path.') 37 26 38 27 39 class MediaFolder(models.Model): … … 32 44 name = models.CharField(max_length=255) 33 45 parent = models.ForeignKey('self', null=True, blank=True, related_name='children') 34 46 35 47 def __unicode__(self): 36 48 return "%s/%s" % ('/'.join(self.get_ancestors().values_list('name', flat=True)), self.name) … … 68 80 limit_choices_to={'app_label': 'media'}, 69 81 editable=False, null=True) 70 82 71 83 staffers = models.ManyToManyField(Staffer, through='MediaByline', related_name='media') 72 84 staffers_override = models.CharField(max_length=255, blank=True, … … 78 90 associations, esp. for one-off \ 79 91 contributors.") 80 92 81 93 slug = models.SlugField() 82 94 83 95 created_at = CreationDateTimeField() 84 96 modified_at = ModificationDateTimeField() 85 97 published_at = models.DateTimeField() 86 98 87 99 tags = TagField() 88 100 89 101 def default_comment_option(): 90 102 try: … … 98 110 99 111 comment_options = models.ForeignKey(CommentOptions, null=True, default=default_comment_option) 100 101 objects = SubclassManager() 102 103 class Meta: 104 ordering = ["-created_at"] 105 get_latest_by = "-created_at" 106 112 113 objects = SubclassManager() 114 115 class Meta: 116 ordering = ["-created_at"] 117 get_latest_by = "-created_at" 118 107 119 def __unicode__(self): 108 120 return "Media: %s" % self.name 109 121 110 122 def save(self, *args, **kwargs): 111 123 if(not self.content_type): 112 124 self.content_type = ContentType.objects.get_for_model(self.__class__) 113 125 self.save_base(*args, **kwargs) 114 126 115 127 @models.permalink 116 128 def get_absolute_url(self): … … 131 143 return self 132 144 return model.objects.get(id=self.id) 133 145 134 146 def admin_thumbnail(self): 135 147 """ … … 153 165 """ 154 166 media_item = models.ForeignKey(MediaItem) 155 167 156 168 class ContentMedia(models.Model): 157 169 """ … … 161 173 media_item = models.ForeignKey(MediaItem) 162 174 order = models.PositiveSmallIntegerField() 163 175 164 176 class Meta: 165 177 abstract = True 166 178 ordering = ['order'] 167 179 168 180 class Photo(MediaItem): 169 181 """ … … 171 183 """ 172 184 image = models.ImageField(_('image'), upload_to=get_storage_path) 173 174 objects = SubclassManager() 175 176 class Meta: 177 ordering = ["-created_at"] 178 get_latest_by = "-created_at" 179 185 186 objects = SubclassManager() 187 188 class Meta: 189 ordering = ["-created_at"] 190 get_latest_by = "-created_at" 191 180 192 def __unicode__(self): 181 193 return u"Photo: %s" % self.name 182 194 183 195 def thumbnail(self): 184 196 return self.image … … 195 207 image = models.ImageField("Thumbnail", upload_to=get_storage_path, blank=True, 196 208 help_text="Leave blank to automatically fetch from external service.") 197 198 objects = SubclassManager() 199 200 class Meta: 201 ordering = ["-created_at"] 202 get_latest_by = "-created_at" 203 209 210 objects = SubclassManager() 211 212 class Meta: 213 ordering = ["-created_at"] 214 get_latest_by = "-created_at" 215 204 216 def __unicode__(self): 205 217 return u"Video: %s" % self.name 206 218 207 219 def save(self, **kwargs): 208 220 if not self.image: … … 218 230 self.image = filename 219 231 super(Video, self).save(**kwargs) 220 232 221 233 def thumbnail(self): 222 234 return self.image … … 228 240 """ 229 241 file = models.FileField(upload_to=get_file_path) 230 231 class Meta: 232 ordering = ["-created_at"] 233 get_latest_by = "-created_at" 234 242 243 class Meta: 244 ordering = ["-created_at"] 245 get_latest_by = "-created_at" 246 235 247 def __unicode__(self): 236 248 return u"Audio: %s" % self.name 237 249 gettag.register(Audio) 238 250 239 251 class Gallery(MediaItem): 240 252 """ … … 244 256 media = models.ManyToManyField(MediaItem, through='GalleryMedia', 245 257 related_name='galleries', symmetrical=False) 246 247 objects = SubclassManager() 248 258 259 objects = SubclassManager() 260 249 261 def __init__(self, *args, **kwargs): 250 262 super(Gallery, self).__init__(*args, **kwargs) 251 263 252 264 # fetch the first item in the gallery to be used for thumbnail purposes 253 265 try: … … 255 267 except: 256 268 pass 257 269 258 270 class Meta: 259 271 verbose_name_plural = 'galleries' 260 272 ordering = ["-created_at"] 261 273 get_latest_by = "-created_at" 262 274 263 275 def __unicode__(self): 264 276 return u"Gallery: %s" % self.name 265 277 266 278 def thumbnail(self): 267 279 return self.image 268 gettag.register(Gallery) 280 gettag.register(Gallery) 269 281 270 282 class GalleryMedia(ContentMedia): … … 273 285 """ 274 286 gallery = models.ForeignKey(Gallery, related_name='gallery_media') 275 287 288 """ 289 GalleryUpload model originally based on model from django-photologue (r405, February 6, 2010). 290 django-photologue is Copyright (c) 2007-2008, Justin C. Driscoll. All rights reserved. 291 """ 292 class GalleryUpload(models.Model): 293 zip_file = models.FileField(_('images file (.zip)'), upload_to=get_temp_file_path, 294 help_text=_('Select a .zip file of images to upload into a new Gallery.')) 295 gallery = models.ForeignKey(Gallery, null=True, blank=True, help_text=_('Select a gallery to add these images to. leave this empty to create a new gallery from the supplied title.')) 296 name = models.CharField(max_length=255, help_text=_('All photos in the gallery will be given a name made up of the gallery name + a sequential number.')) 297 caption = models.TextField(help_text=_('Caption will be added to all photos.')) 298 caption_photos = models.BooleanField(default=True, help_text=_('Gallery caption will also be applied to each photo.')) 299 staffer = models.ForeignKey(Staffer) 300 published_at = models.DateTimeField() 301 302 class Meta: 303 verbose_name = _('gallery upload') 304 verbose_name_plural = _('gallery uploads') 305 306 def save(self, *args, **kwargs): 307 super(GalleryUpload, self).save(*args, **kwargs) 308 gallery = self.process_zipfile() 309 super(GalleryUpload, self).delete() 310 return gallery 311 312 def process_zipfile(self): 313 if os.path.isfile(self.zip_file.path): 314 # TODO: implement try-except here 315 zip = zipfile.ZipFile(self.zip_file.path) 316 bad_file = zip.testzip() 317 if bad_file: 318 raise Exception('"%s" in the .zip archive is corrupt.' % bad_file) 319 count = 1 320 if self.gallery: 321 gallery = self.gallery 322 else: 323 gallery = Gallery.objects.create(name=self.name, 324 slug=slugify(self.name), 325 caption=self.caption, 326 published_at=self.published_at) 327 328 MediaByline(media_item=gallery, staffer=self.staffer, order=1).save() 329 330 from cStringIO import StringIO 331 for filename in sorted(zip.namelist()): 332 if filename.startswith('__'): # do not process meta files 333 continue 334 data = zip.read(filename) 335 if len(data): 336 try: 337 # the following is taken from django.newforms.fields.ImageField: 338 # load() is the only method that can spot a truncated JPEG, 339 # but it cannot be called sanely after verify() 340 trial_image = Image.open(StringIO(data)) 341 trial_image.load() 342 # verify() is the only method that can spot a corrupt PNG, 343 # but it must be called immediately after the constructor 344 trial_image = Image.open(StringIO(data)) 345 trial_image.verify() 346 except Exception, e: 347 # if a "bad" file is found we just skip it. 348 assert False, ('Bad file in zip upload', e) 349 continue 350 while 1: 351 name = ' '.join([self.name, str(count)]) 352 slug = slugify(name) 353 try: 354 p = Photo.objects.get(slug=slug) 355 except Photo.DoesNotExist: 356 photo = Photo(name=name, 357 slug=slug, 358 published_at=self.published_at) 359 photo.caption = self.caption if self.caption_photos else '' 360 photo.image.save(filename, ContentFile(data)) 361 photo.save() 362 363 MediaByline(media_item=photo, staffer=self.staffer, order=1).save() 364 365 GalleryMedia(gallery=gallery, media_item=photo, order=count).save() 366 count = count + 1 367 break 368 count = count + 1 369 zip.close() 370 return gallery 371 276 372 class File(MediaItem): 277 373 """ … … 281 377 image = models.ImageField("Thumbnail", upload_to=get_storage_path, blank=True, 282 378 help_text="Leave blank to generate automatically.") 283 379 284 380 width = models.PositiveIntegerField(blank=True, null=True, help_text="Only required for certain file types (e.g., SWF)") 285 381 height = models.PositiveIntegerField(blank=True, null=True, help_text="Only required for certain file types (e.g., SWF)") 286 287 objects = SubclassManager() 288 289 class Meta: 290 ordering = ["-created_at"] 291 get_latest_by = "-created_at" 292 382 383 objects = SubclassManager() 384 385 class Meta: 386 ordering = ["-created_at"] 387 get_latest_by = "-created_at" 388 293 389 def thumbnail(self): 294 390 return self.image if self.image else self.file 295 391 296 392 def extension(self): 297 393 """