luisbm
luisbm

Reputation: 3

Python calling a property from inside a class

I'm trying to call the property protocolo on a new imagefield's upload_to argument

What I'm trying to accomplish is to have the saved images use a custom filename.

class biopsia(models.Model):
    paciente = models.CharField(max_length=50)
    creado = models.DateTimeField(auto_now_add=True)
    foto = models.ImageField(upload_to=f'fotos_biopsias/%Y/{protocolo}', blank=True)

    def __str__(self):
        return str(self.protocolo)

    @property
    def protocolo(self):
        return 'BIO' + str(self.creado.year) + '-' + str(biopsia._base_manager.filter(
            creado__year=self.creado.year,
            creado__lt=self.creado
        ).count() + 1)

File "models.py", line 30, in biopsia
    foto = models.ImageField(upload_to=f'fotos_biopsias/%Y/{protocolo}', blank=True)
NameError: name 'protocolo' is not defined 

I've tried defining an outside method for upload_to but still I cannot use it inside my class

Upvotes: 0

Views: 39

Answers (1)

ruddra
ruddra

Reputation: 51988

You can follow the official documentation on how to use function as path for ImageField. Basically, you need to define a function in outer scope of the Model class. For your case, you can try the following code:

def protocolo(instance, filename):
    return f'fotos_biopsias/{timezone.now().year}/BIO' + str(instance.creado.year) + '-' + str(instance.__class__._base_manager.filter(
        creado__year=instance.creado.year,
        creado__lt=instance.creado
    ).count() + 1) + "/" + filename


class biopsia(models.Model):
    paciente = models.CharField(max_length=50)
    creado = models.DateTimeField(auto_now_add=True)
    foto = models.ImageField(upload_to=protocolo, blank=False, null=False)

    def __str__(self):
        foto_path = self.foto.path.split('/')[3:]
        return '/'.join(foto_path)

To be honest, it feels over calculating in DB level for simple storing the images. If it is only about how to show image in a particular url path, you can consider writing a view which acts as wrapper at that url path for downloading images. You can follow this example given here: Django: Serving Media Behind Custom URL.

Upvotes: 1

Related Questions