ក្រុម រូបភាព ថតឯកសារ វ៉ែប
Recently Visited Groups | Help | Sign in
Google Groups Home
Using a dynamically created ImageField filename prior to save?
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  9 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Andrew Turner  
View profile  
 More options Jun 30 2009, 6:27 pm
From: Andrew Turner <acturne...@gmail.com>
Date: Tue, 30 Jun 2009 12:27:00 +0100
Subject: Using a dynamically created ImageField filename prior to save?
Hi,

This is an issue which, I believe, is related to Ticket #10788
(http://code.djangoproject.com/ticket/10788).

The following code snippet used to work with Django 1.0.2, but with
the latest svn version the slug is not being set to the filename
produced by get_path because, as I understand it, get_path will not be
called until the instance is saved to the database.

def get_path(instance, filename):
    salt = hashlib.sha1(str(random.random())).hexdigest()
    name = hashlib.sha1(salt+filename).hexdigest()[:16]
    return '%s.jpg' % (name)

class Photo(models.Model):
    photo = models.ImageField(upload_to=get_path, blank=False)
    ...
    slug = models.CharField(max_length=16, unique=True)

    def save(self):
        self.slug = self.photo.url.split('/')[-1:][0].split('.')[0]
        super(Photo, self).save()

I could call instance.save() twice in my view to force it to use the
correct name, but this feels a bit messy to me. What's the best way to
get the correct value for the slug field prior to saving it to the
database, given that the filename is 'randomly' generated?

Cheers,
Andrew


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andrew Turner  
View profile  
 More options Jul 1 2009, 3:59 pm
From: Andrew Turner <acturne...@gmail.com>
Date: Wed, 1 Jul 2009 09:59:48 +0100
Local: Wed, Jul 1 2009 3:59 pm
Subject: Re: Using a dynamically created ImageField filename prior to save?
2009/6/30 Andrew Turner <acturne...@gmail.com>:

e.g. Generated filename:-

    ebc151e5aad64f4b.jpg

Derived url for Photo view:-

    http://mydomain.com/photo/ebc151e5aad64f4b

From reading the above mentioned ticket and it's referenced discussion
threads, I can't see any way of generating a slug field from the
filename before the instance is saved. At the moment I am saving the
instance to generate the hashed filename, creating the slug based on
the dynamically generated filename, and then saving to the database
again.

Doesn't seem ideal to me, especially as it worked without the extra
save in 1.0.2, and I'm using this dynamic filename/slug method on
several projects.

Cheers,
Andrew


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rajesh D  
View profile  
 More options Jul 2 2009, 3:39 am
From: Rajesh D <rajesh.dha...@gmail.com>
Date: Wed, 1 Jul 2009 13:39:17 -0700 (PDT)
Local: Thurs, Jul 2 2009 3:39 am
Subject: Re: Using a dynamically created ImageField filename prior to save?

Judging by the discussions on the above mentioned ticket, it may be a
while before this behaviour is reverted back (if it is reverted back
at all.)

There's a subtle bug in this line of your code:

self.slug = self.photo.url.split('/')[-1:][0].split('.')[0]

It assumes that the expression will never result in a slug whose
length is more than 16. But that's not necessarily true because when
Django tries to save your photo file and finds another file with the
same name, it will append an underscore to the filename until it
generates a unique filename. In that case, your slug will extend
beyond its 16 character limit. Since your filenames are generated
randomly, it's not very likely that you will ever hit this edge case.
But just be aware.

As for your problem of computing a slug based on the filename, perhaps
the following will help:

def get_path(instance, filename):
    salt = hashlib.sha1(str(random.random())).hexdigest()
    name = hashlib.sha1(salt+filename).hexdigest()[:16]
    # Save generated filename in an attribute of this model instance:
    instance._my_filename = name
    return '%s.jpg' % (name)

Then, in the model save do:

if not self.slug:
    self.slug = self._my_filename

If this does work, you might still have to add some more defensive
code around there to check that the instance "hasattr" _my_filename
and if it doesn't, may be just generated a random 16 character slug.

-RD


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andrew Turner  
View profile  
 More options Jul 2 2009, 2:17 pm
From: Andrew Turner <acturne...@gmail.com>
Date: Thu, 2 Jul 2009 08:17:45 +0100
Local: Thurs, Jul 2 2009 2:17 pm
Subject: Re: Using a dynamically created ImageField filename prior to save?
2009/7/1 Rajesh D <rajesh.dha...@gmail.com>:

> Judging by the discussions on the above mentioned ticket, it may be a
> while before this behaviour is reverted back (if it is reverted back
> at all.)

I'm not seeking to have the new behaviour reversed - if the powers
that be say the new way is more robust, I'm happy to go along with
that. But I think it is important to realise that it is a backwards
incompatible change, and there are real use cases for the old
behaviour.

> There's a subtle bug in this line of your code:

> self.slug = self.photo.url.split('/')[-1:][0].split('.')[0]

> It assumes that the expression will never result in a slug whose
> length is more than 16. But that's not necessarily true because when
> Django tries to save your photo file and finds another file with the
> same name, it will append an underscore to the filename until it
> generates a unique filename. In that case, your slug will extend
> beyond its 16 character limit. Since your filenames are generated
> randomly, it's not very likely that you will ever hit this edge case.
> But just be aware.

Duplicate filenames are checked for elsewhere in my code (I only
presented a truncated version for clarity), so there shouldn't be a
case where underscores are used, and the slug will always be unique
(unless there are so many uploads, I run out of 16 hex digit
combinations!).

I don't think this will work, as get_path() will not be called until
the model is saved. So the _my_filename attribute will not be
available to the code in the save method before the super(Photo,
self).save() line.

Would it be possible to define the hashed filename in the save method,
and then pass it to the upload_to argument of the ImageField?

Thank you for your reply,
Andrew


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andrew Turner  
View profile  
 More options Jul 2 2009, 6:11 pm
From: Andrew Turner <acturne...@gmail.com>
Date: Thu, 2 Jul 2009 12:11:04 +0100
Local: Thurs, Jul 2 2009 6:11 pm
Subject: Re: Using a dynamically created ImageField filename prior to save?
2009/7/2 Andrew Turner <acturne...@gmail.com>:

> Would it be possible to define the hashed filename in the save method,
> and then pass it to the upload_to argument of the ImageField?

In answer to my own question, this seems to work:-

def get_path(instance, name):
   return instance._my_filename

class Photo(models.Model):
   photo = models.ImageField(upload_to=get_path, blank=False)
   ...
   slug = models.CharField(max_length=16, unique=True)

   def save(self):
        name = hashlib.sha1(str(random.random())).hexdigest()[:16]
        self._my_filename = '%s.jpg' % (name)
        self.slug = name
        super(Post, self).save()

Cheers,
Andrew


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andrew Turner  
View profile  
 More options Jul 2 2009, 6:29 pm
From: Andrew Turner <acturne...@gmail.com>
Date: Thu, 2 Jul 2009 12:29:29 +0100
Local: Thurs, Jul 2 2009 6:29 pm
Subject: Re: Using a dynamically created ImageField filename prior to save?
2009/7/2 Andrew Turner <acturne...@gmail.com>:

Talking to myself again, I've changed the save method slightly:-

    def save(self):
        if not self.slug:
            name = hashlib.sha1(str(random.random())).hexdigest()[:16]
            self._my_filename = '%s.jpg' % (name)
            self.slug = name
        super(Post, self).save()

and added a blank=True to the slug field so that it only sets it on
the first save.

If there is a better way of doing all this, feel free to let me know.
If not, I hope this is of use to somebody.

Thanks for your pointers, Rajesh.

Cheers,
Andrew


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andrew Turner  
View profile  
 More options Jul 2 2009, 6:47 pm
From: Andrew Turner <acturne...@gmail.com>
Date: Thu, 2 Jul 2009 04:47:30 -0700 (PDT)
Local: Thurs, Jul 2 2009 6:47 pm
Subject: Re: Using a dynamically created ImageField filename prior to save?
On Jul 2, 12:29 pm, Andrew Turner <acturne...@gmail.com> wrote:

> Talking to myself again, I've changed the save method slightly:-

>     def save(self):
>         if not self.slug:
>             name = hashlib.sha1(str(random.random())).hexdigest()[:16]
>             self._my_filename = '%s.jpg' % (name)
>             self.slug = name
>         super(Post, self).save()

Oh, and it's obviously supposed to read super(Photo, self).save()

    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mirat Can Bayrak  
View profile  
 More options Jul 6 2009, 3:42 am
From: Mirat Can Bayrak <miratcanbay...@gmail.com>
Date: Sun, 5 Jul 2009 23:42:16 +0300
Local: Mon, Jul 6 2009 3:42 am
Subject: Re: Using a dynamically created ImageField filename prior to save?
I have another question. You are naming images as hash of random number. There is a small chance to produce same name i think. It is not good way to give name ha?

--
Mirat Can Bayrak <miratcanbay...@gmail.com>


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andrew Turner  
View profile  
 More options Jul 6 2009, 4:41 pm
From: Andrew Turner <acturne...@gmail.com>
Date: Mon, 6 Jul 2009 10:41:35 +0100
Local: Mon, Jul 6 2009 4:41 pm
Subject: Re: Using a dynamically created ImageField filename prior to save?
2009/7/5 Mirat Can Bayrak <miratcanbay...@gmail.com>:

> I have another question. You are naming images as hash of random number. There is a small chance to produce same name i think. It is not good way to give name ha?

The slug field has a unique=True argument, so if the same file name
does happen to be produced, it can't be saved to the database, and the
user will have to try again.

    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2010 Google