Thanks, that was very helpful. I had another pointer on this and found out that the easiest way to do this is just to change the ```file``` line in the class to:

```
file = ImageField(_('image'), upload_to='images/items/%Y/%m/%d/% H/%M/%S')
````

There are a few things that I do not understand, however, after playing around with some code for a while.

If I just pass a string to ```file``` it understands that this is a partial path, and it has to stick ```filename``` on the end. eg:

```file = ImageField(_('image'), upload_to='images/items')```

Likewise with the version above with the date formatting.

This is also the case when I used my initial ```upload_path``` function, calling it with ```upload_to=upload_path()``` – but this did not suit the task, because ```upload_path``` loaded at initialisation of the server.

So, given that ```upload_path``` returns a string, I don't understand why I also have to concatenate the ```filename```:

```
def upload_path(instance, filename):
        dtnow = datetime.now(timezone.utc)
        dtstr = '{:%Y/%m/%d}'.format(dtnow)
        dtstr = 'images/items/' + dtstr + '/' + filename
        return dtstr
```
In this case, if I do not concatenate ```filename``` then the uploaded file gets named with the last element of the date formatting and without a file extension, ie potentially like this:

```images/items/2020/10/28/20/59/55```

rather than:

```images/items/2020/10/28/20/59/55/image.jpg```

The other thing I don't understand is how ```instance``` and ```filename``` are passed to the function ```upload_path```. I would expect to do something like:

``` file = ImageField(_('image'), upload_to=upload_path(instance, filename))```

But if I do that I get:

```NameError: name 'instance' is not defined```

Sorry for so many more questions!


-- Clive

On 28 Oct 2020, at 08:58, Carles Pina i Estany wrote:


Hi,

On Oct/27/2020, Clive Bruton wrote:

I have a function that uses the current date to set up a file path for
uploaded images:

********************

def upload_path():

[...]

class Image(models.Model):
        item = models.ForeignKey(Item, on_delete=models.CASCADE)
        #file = ImageField(_('image'), upload_to='images')
        file = ImageField(_('image'), upload_to=upload_path())


The problem is that when the Image class calls 'upload_path' the
datetime portion of this is always the runserver initialisation time,
rather than the time when 'upload_path' is called/used.

How to fix this?

For what I remeber (I use FileField usually but this is noto relevant I
hope) you should do:

def upload_path(instance, filename):
# you have access to the instance (object model Image in your case)
    # and the filename that the user used to upload it
    # and this is executed on the upload time
    return your_new_file_name

In the model:
    file = ImageField(_('image'), upload_to=upload_path)

note that upload_path is a callable: it gets called on the upload time.
In your code it was called on initialization time.

Some time ago I had a similar code that caused a bug: in a ListView the
"queryset = " is executed on startup time. For a dynamic one I should
have used get_queryset() method.

--
Carles Pina i Estany
https://carles.pina.cat

--
You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/ d/msgid/django-users/20201028085843.GA20091%40pina.cat.


--
You received this message because you are subscribed to the Google Groups "Django 
users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/2FBF21DA-2057-4302-BED8-629F9C835337%40indx.co.uk.

Reply via email to