I am trying to create a folder for each users to put their project in. So their file will have the path ..\project\id\filename
, id
is the user id
and filename
is the name of the file. Now using the arguments allowed for upload_to
(instance
and filename
) in the Filefield
, I realize that instance.id
will be None
and the path to the file will be ..\project\None\filename
instead of ..\project\id\filename
.
Now reading the Django documentation upload_to I saw this:
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.
My interpretation is that creating a new record and user_directory_path
are not instantiated at the same time, that is, when I call create
on Project
model, instance.id
will be None
. My question is now, is there a way to get around this? While I see upload_to
convenient, it is not necessarily convenient for dynamic path such as the one I am doing. I was thinking of creating the record, then adding the file path in an update, but I am in search of a way that can save everything in one step.
models.py
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'project/{0}/{1}'.format(instance.user.id, filename)
class Project(models.Model):
email = models.ForeignKey(User,
to_field="email",
max_length=50
)
title = models.CharField(max_length=100)
date_created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
file = models.FileField(upload_to=user_directory_path, validators=[validate_file_type], null=True)
This is views.py
when the form passes validation. Notice user_directory_path
is called just before the create
.
email = request.user.email
title = request.POST.get('title', '')
file = request.FILES['file']
filename = file.name
instance = Usermie.objects.get(email=request.user.email)
# Save to model
user_directory_path(instance=instance, filename=filename)
Project.objects.create(
title=title, file=file,
)