import requests from io import BytesIO from django.conf import settings from django.core.files.uploadedfile import InMemoryUploadedFile from django.db import models from django.dispatch import receiver from django_images.models import Image as BaseImage, Thumbnail from taggit.managers import TaggableManager from users.models import User class ImageManager(models.Manager): _default_ua = { 'User-Agent': 'Mozilla/5.0 (Windows NT 5.1) ' 'AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/48.0.2564.82 Safari/537.36', } # FIXME: Move this into an asynchronous task def create_for_url(self, url, referer=None): file_name = url.split("/")[-1].split('#')[0].split('?')[0] buf = BytesIO() headers = dict(self._default_ua) if referer is not None: headers["Referer"] = referer response = requests.get(url, headers=headers) buf.write(response.content) obj = InMemoryUploadedFile(buf, 'image', file_name, None, buf.tell(), None) # create the image and its thumbnails in one transaction, removing # a chance of getting Database into a inconsistent state when we # try to create thumbnails one by one later image = self.create(image=obj) Thumbnail.objects.get_or_create_at_sizes(image, settings.IMAGE_SIZES.keys()) return image class Image(BaseImage): objects = ImageManager() class Sizes: standard = "standard" thumbnail = "thumbnail" square = "square" class Meta: proxy = True @property def standard(self): return Thumbnail.objects.get( original=self, size=self.Sizes.standard ) @property def thumbnail(self): return Thumbnail.objects.get( original=self, size=self.Sizes.thumbnail ) @property def square(self): return Thumbnail.objects.get( original=self, size=self.Sizes.square ) class Board(models.Model): class Meta: unique_together = ("submitter", "name") index_together = ("submitter", "name") submitter = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=128, blank=False, null=False) private = models.BooleanField(default=False, blank=False) pins = models.ManyToManyField("Pin", related_name="pins", blank=True) published = models.DateTimeField(auto_now_add=True) class Pin(models.Model): submitter = models.ForeignKey(User, on_delete=models.CASCADE) private = models.BooleanField(default=False, blank=False) url = models.CharField(null=True, blank=True, max_length=2048) referer = models.CharField(null=True, blank=True, max_length=2048) description = models.TextField(blank=True, null=True) image = models.ForeignKey(Image, related_name='pin', on_delete=models.CASCADE) published = models.DateTimeField(auto_now_add=True) tags = TaggableManager() def tag_list(self): return self.tags.all() def __unicode__(self): return '%s - %s' % (self.submitter, self.published) @receiver(models.signals.post_delete, sender=Pin) def delete_pin_images(sender, instance, **kwargs): try: instance.image.delete() except Image.DoesNotExist: pass