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:
- Duplicating the image relationship in both concrete models (seems redundant)
- 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
orManyToMany relationships
in abstract models
No. Django allows to define ForeignKey
s, ManyToManyField
s, 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