Tony
Tony

Reputation: 125

Autopopulate Imagefield in a Django model upon saving

I currently have this:

class youtube_video(models.Model):
   video_url = models.CharField(max_length=150,blank=True, validators=[RegexValidator("^.*((v\/)|(embed\/)|(watch\?))\??v?=?(?P<vid_id>[^\&\?]*).*")])
   video_thumbnail = models.ImageField(upload_to="/thumbs")

   def save(self, args*, kwargs**):
      video_thumbnail = urllib2.urlretrieve(#trivial regex here that gets the thumbnail url from the video_url)
      super(youtube_video, self).save(*args, **kwargs)

This isn't working, but hopefully it demonstrates what I'm trying to do. Essentially I want to autopopulate the video_thumbnail ImageField upon the model saving, using another field in the model.

Upvotes: 2

Views: 969

Answers (2)

Jo&#227;o Pesce
Jo&#227;o Pesce

Reputation: 2494

My answer is heavily based on the previous answer, but it didn't work as presented, so here are two versions that should work:

from django.core.files import File
from django.core.files.temp import NamedTemporaryFile
import urllib2

class SomeModel(models.Model):
    # Some attributes...
    image = models.ImageField(upload_to='dir')

      def save(self, *args, **kwargs):
        url = 'http://www.path.to.image.com/image.jpg'
        img_temp = NamedTemporaryFile(delete=True)
        img_temp.write(urllib2.urlopen(url).read())
        img_temp.flush()
        self.image.save('name_of_your_image.jpg',File(img_temp),save=False)
        super(SomeModel, self).save(*args, **kwargs)

If you don't care about the name of the image being saved on your media folder, you can do:

from django.core.files import File
from django.core.files.temp import NamedTemporaryFile
import urllib2

class SomeModel(models.Model):
    # Some attributes...
    image = models.ImageField(upload_to='dir')

      def save(self, *args, **kwargs):
        url = 'http://www.path.to.image.com/image.jpg'
        img_temp = NamedTemporaryFile(delete=True)
        img_temp.write(urllib2.urlopen(url).read())
        img_temp.flush()
        self.image = File(img_temp)
        super(SomeModel, self).save(*args, **kwargs)

Upvotes: 0

Josh Smeaton
Josh Smeaton

Reputation: 48710

Remember you need to reference self from within instance methods.

def save(self, args*, kwargs**):
      self.video_thumbnail = urllib2.urlretrieve(...)
      super(youtube_video, self).save(*args, **kwargs)

However there's still a problem. urlretrieve returns a (filename, headers) tuple, not a valid File object.

See this question on how to retrieve a file for an ImageField.

Edit:

from django.core.files import File
from django.core.files.temp import NamedTemporaryFile

def save(self, args*, kwargs**):
    img_temp = NamedTemporaryFile(delete=True)
    img_temp.write(urllib2.urlopen(..regex..).read())
    img_temp.flush()
    file_name = 'determine filename'
    self.video_thumbnail.save(file_name, File(img_temp))
    super(youtube_video, self).save(*args, **kwargs)

The above is based on the answer linked above, and reading about FileField in the Django documentation. I haven't had to work with FileFields myself, so I hope this is helpful.

Upvotes: 2

Related Questions