Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic File Path in Django

I'm trying to generate dynamic file paths in django. I want to make a file system like this:

 -- user_12
     --- photo_1
     --- photo_2
 --- user_ 13
     ---- photo_1

I found a related question : Django Custom image upload field with dynamic path

Here, they say we can change the upload_to path and leads to https://docs.djangoproject.com/en/stable/topics/files/ doc. In the documentation, there is an example :

from django.db import models
from django.core.files.storage import FileSystemStorage

fs = FileSystemStorage(location='/media/photos')

class Car(models.Model):
    ...
    photo = models.ImageField(storage=fs)

But, still this is not dynamic, I want to give Car id to the image name, and I cant assign the id before Car definition completed. So how can I create a path with car ID ??

like image 335
iva123 Avatar asked Feb 27 '11 20:02

iva123


3 Answers

You can use a callable in the upload_to argument rather than using custom storage. See the docs, and note the warning there that the primary key may not yet be set when the function is called. This can happen because the upload may be handled before the object is saved to the database, so using ID might not be possible. You might want to consider using another field on the model such as slug. E.g:

import os
def get_upload_path(instance, filename):
    return os.path.join(
      "user_%d" % instance.owner.id, "car_%s" % instance.slug, filename)

then:

photo = models.ImageField(upload_to=get_upload_path)
like image 168
DrMeers Avatar answered Oct 21 '22 18:10

DrMeers


You can use lambda function as below, take note that if instance is new then it won't have the instance id, so use something else:

logo = models.ImageField(upload_to=lambda instance, filename: 'directory/images/{0}/{1}'.format(instance.owner.id, filename))
like image 40
James Lin Avatar answered Oct 21 '22 18:10

James Lin


https://docs.djangoproject.com/en/stable/ref/models/fields/#django.db.models.FileField.upload_to

def upload_path_handler(instance, filename):
    return "user_{id}/{file}".format(id=instance.user.id, file=filename)

class Car(models.Model):
    ...
    photo = models.ImageField(upload_to=upload_path_handler, storage=fs)

There is a warning in the docs, but it shouldn't affect you since we're after the User ID and not the Car ID.

In most cases, this object will not have been saved to the database yet, so if it uses the default AutoField, it might not yet have a value for its primary key field.

like image 6
Yuji 'Tomita' Tomita Avatar answered Oct 21 '22 16:10

Yuji 'Tomita' Tomita