Search code examples
djangodjango-modelsdjango-admin

why i get None instead of the model id in django ImageField path


When attempting to add a new event through the Django admin panel, the image is incorrectly being stored at the path "media/events/None/poster/file.png" instead of the intended path "media/events/{instance.id}/poster/file.png."

I have added a print(...) statement to the get_poster_image_path function for testing purposes. :

def get_poster_image_path(instance, filename):
    print(f"""
    from get_poster_image_path ==================\n
    type :{type(instance)}\n
    instance :{instance}\n
    instance.id :{instance.id}\n
    instance.name :{instance.name}
    """)
    return f'events/{instance.id}/poster/{filename}'


class Event(models.Model):
    name = models.CharField(max_length=50)
    poster = models.ImageField(upload_to=get_poster_image_path,null=True,blank=True)
    ....

the result:

from get_poster_image_path =============================
type :<class 'events.models.Event'>                                    
instance :myevent                                                           
instance.id :None
instance.name :myevent    

Solution

  • i think that i finaly I've finally found a solution. know that it not the best one but it works

    class Event(models.Model):
        name = models.CharField(max_length=50)
        poster = models.ImageField(upload_to=get_poster_image_path,null=True,blank=True)
    
    
        def save(self, *args, **kwargs):
            super().save(*args, **kwargs)
            # Open the image using Pillow
            img = Image.open(self.poster.path)
    
            # Specify the custom path to save the modified image
            original_filename = os.path.basename(self.poster.name)
            
            # create the directory if it not exists
            directory_path = os.path.join('media','events', str(self.id), 'poster')
            os.makedirs(directory_path, exist_ok=True)
            
            # save the image in the right place
            custom_path = os.path.join(directory_path, original_filename)
            img.save(custom_path)
            
            # change the poster to the new path 
            self.poster =  os.path.join('events',str(self.id),'poster', original_filename)
            
            # remove the old file
            to_remove = os.path.join('media','events',"None")
            if os.path.exists(to_remove) :
                shutil.rmtree(to_remove)
                
            super().save(*args, **kwargs)