djangodjango-modelsabstract-base-class

Django: Override model methods from abstract base class models


I am trying to use an abstract base class model in Django to avoid writing some duplicate code and encountering some unexpected behavior.

Here is simplified version of my abstract base class:

class AbstractDocument(models.Model):
  notes = models.CharField(max_length=255)
  document = models.FileField(upload_to=document_file_path)

  def document_file_path(instance, filename):
    pass

  class Meta:
    abstract = True    

I need to define the method document_file_path or the code generates error. I want to define different behavior in the subclasses for the document_file_path. Below is an example:

class BookDocument(AbstractDocument):
  book = models.ForeignKey(Book, on_delete=models.CASCADE)

  def document_file_path(instance, filename):
    return f'books/{filename}'

It does not appear that the child method is overriding the parent method because I get an error that document_file_path returned NoneType when I run the code above. I tried making the method in AbstractDocument return an actual path, but the child method doesn't override the parent in that scenario either.

Is there some reason why what I'm trying to do is not possible? Is there something I'm missing in the implementation? Is there another or better way to accomplish this?


Solution

  • Field is a class attribute, not instance, but you're trying to link it to an instance's method which is not really possible/correct.

    So try marking your method as a @staticmethod or switch to a solution similar to proposed in the second answer here: make a "simple" function calling instance's (which is the first argument in upload_to) method, which can be inherited and overridden.