How to set up a callable for Django Imagefield's >> default << parameter

Question:

So I have a Model that will contain a couple hundred instances and I now added an imagefield logo. As I don’t want to upload each and every logo via the admin manually, I want to set up a callable that returns the correct file path so I can just push the logos to media/company_logos. Due to some technical hick-up I can push the logos to the folder only after creating their instance.

# models.py

def logo_directory_path(instance, filename):
    return f'company_logos/{instance.symbol}'

class Company(models.Model):

    symbol = models.CharField(max_length=50)
    logo = models.ImageField(upload_to='company_logos/', default=logo_directory_path(instance=symbol, filename=f'{symbol}.png'))

This returns an error at instance=symbol saying

Type ‘str’ doesn’t have expected attribute ‘symbol’

Another approach was

logo = models.ImageField(upload_to='company_logos/', default=f'company_logos/{symbol}')

which returns a URL as src="/media/company_logos/<django.db.models.fields.CharField>"

I am not quiet sure how to set this up as I cant fully understand the official docs.

My desired outcome is to have a URL for default like so:

company_logos/IBM.png with field symbol being the corresponding part (I tried it via f-string).

Update to Ankits request –> When trying to create a new instance with the code suggested it throws

logo_directory_path() missing 2 required positional arguments:
‘instance’ and ‘filename’

Asked By: JSRB

||

Answers:

Here is the updated code

def logo_directory_path(instance, filename):
    if not hasattr(instance, 'symbol'):
       return f'company_logos/{filename}'
    return f'company_logos/{instance.symbol}'

class Company(models.Model):

    symbol = models.CharField(max_length=50)
    logo = models.ImageField(upload_to=logo_directory_path, default=logo_directory_path)

above code will return image path eg.company_logos/IBM.png if your instance have symbol attribute and if not then it will return default symbol of file you can change filename if you don’t want to set default filename of file

Answered By: Ankit Tiwari

You use the logic in the uploaded_to=… parameter [Django-doc], so:

from pathlib import Path


class Company(models.Model):
    def logo_directory_path(self, filename):
        return f'company_logos/{self.symbol}{Path(filename).suffix}'

    symbol = models.CharField(max_length=50)
    logo = models.ImageField(upload_to=logo_directory_path)
Answered By: Willem Van Onsem
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.