In my Django application, I have 2 models: Product
and Image
.
A product can have many images and an image can only belong to a single product.
I want to be able to create a sub-folder for the images of a product with the name of the product itself when images of a product are uploaded. So, in the Image
model, I need to access the title of the product
.
Here is my code:
class Product(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, blank=True, allow_unicode=True)
class Image(models.Model):
name = models.CharField(max_length=255, null=True, blank=True)
product = models.ForeignKey(Product, on_delete=models.CASCADE,
related_name='images')
image = models.ImageField(upload_to=f'product_images/{product.title}/')
In the Image
model, I have an image
field which is of type ImageField
in which I want to get the title of the product
.
I get the following error:
'ForeignKey' object has no attribute 'title'
How can I access the title of the product
inside the Image
model?
The issue is because this line:
image = models.ImageField(upload_to=f'product_images/{product.title}/')
Is evaluated when the model is defined, and in that context 'product.title' doesn't yet make sense: it only makes sense when an instance of the class is created with an associated product.
To get around this, use a helper function like get_upload_to
and pass it as the argument to the upload_to
parameter, as below:
def get_upload_to(instance, filename):
return f'product_images/{instance.product.title}/{filename}'
class Image(models.Model):
name = models.CharField(max_length=255, null=True, blank=True)
product = models.ForeignKey(
Product, on_delete=models.CASCADE, related_name='images')
image = models.ImageField(upload_to=get_upload_to)
This method works because when the get_upload_to
method is called by Django, it will automatically pass both the instance and filename variables to it (see official docs here: https://docs.djangoproject.com/en/4.2/ref/models/fields/#django.db.models.FileField.upload_to )