Passing a callback as upload_to to FileField

I have an abstract model of the UploadItem class for processing uploaded files. I want each subclass to be able to define the upload_to path. To do this, I pass the callback to the FileField constructor.

That's an example:

class UploadItem(models.Model):
    file = models.FileField(upload_to=UploadItem.get_directory) 


    class Meta:
        abstract = True
# I want videos to be storred in 'videos/' directory
class Video(UploadItem):
    def get_directory(self, instance, filename):
        return 'videos/'

But this does not work, I get this error:

file = models.FileField(upload_to=UploadItem.get_directory) 
NameError: name 'UploadItem' is not defined
+3
source share
2 answers

The error is natural, given that during the evaluation

file = models.FileField(upload_to=UploadItem.get_directory) 

class UploadItemis not defined yet. You can do the following to make it work:

def get_directory():
    pass

class UploadItem(models.Model):
    file = models.FileField(upload_to=get_directory)

    class Meta:
        abstract = True

This will not solve all your problems. Adding (or overriding) a method get_directoryin a class Videowill not change the upload_toattribute property of the filemodel.

Refresh

, upload_to .

, , , , . Unix ( ), .

, :

categories_and_paths = { 'video': 'videos/', 'photo': 'photos/' } # etc.
def get_directory(instance, filename):
    category = instance.category
    return categories_and_paths.get(category, '')

Instance . . .

class Video(UploadItem):
    category = 'video'
+5

, :

import os

# ...

def get_directory(instance, filename):
    return instance.get_file_directory(filename)


class UploadItem(models.Model):
    FILE_DIRECTORY = 'files/'

    file = models.FileField(upload_to=get_directory) 

    class Meta:
        abstract = True

    @staticmethod
    def get_file_directory(filename):
        return os.path.join(UploadItem.FILE_DIRECTORY, filename)

:

class Video(UploadItem):
    FILE_DIRECTORY = 'videos/'

    def get_file_directory(self, filename):
        filename = os.path.join(self.FILE_DIRECTORY, filename)
        return super().get_document_path(filename)

, upload_to, :

  • files UploadItem
  • files/videos Video

, .

0

Source: https://habr.com/ru/post/1763844/


All Articles