[Django]-Django instance.id=None when uploading image

6👍

You can’t do it in that way unless you implement your custom dynamic file upload field. Because you try to access instance.id, but instance isn’t saved yet and doesn’t have an id.

Here you are some resources that will help you achieve what you want:

4👍

Another nice way to solve this problem that requires much less code is to have your model use a UUID for the primary key rather then the database generated id. This means at the point the model is saved for the first time the UUID is already known and can be used with any upload_to callbacks.

So for the original example you would do something like this

from django.db import models

import uuid
import os

def get_image_path(instance, filename):
    return os.path.join('photos', "residence_%s" % str(instance.id), filename)

# Create your models here.
class Residence(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    big_image = models.ImageField("Main Image",upload_to=get_image_path)
    small_images = models.ImageField("Small Images",upload_to=get_image_path, blank=True, null=True)

See Django’s UUIDField reference for more info

4👍

If you don’t specify an update_to on the ImageField you could upload to your media root then change the path using a post_save signal.

@receiver(post_save, sender=Product)
def update_file_path(instance, created, **kwargs):
    if created:
        initial_path = instance.image.path
        new_path = settings.MEDIA_ROOT + f'/product_{instance.id}/{instance.image.name}'
        os.makedirs(os.path.dirname(new_path), exist_ok=True)
        os.rename(initial_path, new_path)
        instance.image = new_path
        instance.save()

0👍

you can create a model instance by passing cleaned data from your form as **kwargs to django model i did it that way & its much easier than anything else

in your views post method add this (this code is from my project not adapted to this question)

    pk = request.session['_auth_user_id']
    user_obj = User.objects.get(pk=pk)


    lab_form_instance = lab_form(request.POST,request.FILES)
    lab_form_instance.save(commit=False)
    # here you can put the form.is_valid() statement
    lab_form_instance.cleaned_data['owner'] =user_obj # here iam adding additional needed data for the model
    obj = lab(**lab_form_instance.cleaned_data)
    obj.save()

Leave a comment