How to implement images relationship with Abstract model in Django?

I'm working on a Django project where I have an abstract Post model that serves as a base for two concrete models: RentalPost and RoomSeekingPost. Both of these post types need to have multiple images.

Here's my current model structure:

class Post(BaseModel):
    title = models.CharField(max_length=256)
    content = models.TextField(null=True)
    status = models.CharField(max_length=10, choices=Status, default=Status.PENDING)
    
    class Meta:
        abstract = True

class RentalPost(Post):
    landlord = models.ForeignKey("accounts.User", on_delete=models.CASCADE)
    # other fields specific to rental posts
    
class RoomSeekingPost(Post):
    tenant = models.ForeignKey("accounts.User", on_delete=models.CASCADE)
    # other fields specific to room seeking posts

I want to add image functionality to both post types. Ideally, I'd like to define the image relationship in the abstract Post model since both child models need this functionality.

However, I understand that Django doesn't allow ForeignKey or ManyToMany relationships in abstract models because they can't be properly resolved without a concrete table.

I've considered:

  1. Duplicating the image relationship in both concrete models (seems redundant)
  2. Using generic relations (I not like this approach)

What's the recommended approach for handling this kind of situation where multiple concrete models inheriting from an abstract base need the same relationship?

However, I understand that Django doesn't allow ForeignKey or ManyToMany relationships in abstract models

No. Django allows to define ForeignKeys, ManyToManyFields, etc. on an abstract model. It however does not allow to define relations to an abstract model, which makes sense: to what table should it refer?

But we thus can work with:

class Post(BaseModel):
    title = models.CharField(max_length=256)
    content = models.TextField(null=True)
    status = models.CharField(
        max_length=10, choices=Status, default=Status.PENDING
    )
    image = models.ForeignKey(MyImageModel, on_delete=models.PROTECT)
    other_images = models.ManyToManyField(
        MyImageModel, related_name='%(class)s_other'
    )

    class Meta:
        abstract = True
Back to Top