I have an abstract Django model with two concrete implementations. E.g.
class Animal(models.Model):
name = models.CharField("name", max_length=100)
class Meta:
abstract = True
class Dog(Animal):
...
class Cat(Animal):
...
And then I want to create a generic foreign key that points to a Dog or a Cat. From the documentation about GenericForeignKeys I know that I can do something like
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
class Appointment(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
patient = GenericForeignKey("content_type", "object_id")
But
- I have to do this for every model that can point to a
Dogor aCat. - It doesn't enforce that the foreign key actual points to an
Animal.
Is there a way to set up my Animal model such that in the Appointment model I can just do
class Apointment(models.Model):
patient = GenericRelation(Animal)
To address your requirement of creating a foreign key in Django that points specifically to subclasses of an abstract
Animalmodel (like Dog or Cat in your case), without having to repeat the setup for every model and ensuring that the foreign key indeed points to an Animal subclass, you can create a customModelfield. This custom field for exampleAnimalGenericForeignKey, would be a specialized version of Django'sGenericForeignKey.This custom field would internally use the mechanisms of
GenericForeignKeybut with added logic to ensure the relationship is only withAnimalsubclasses. You need to defineAnimalGenericForeignKeyonce and then use it in any model where you need to reference anAnimalsubclass. When you declare this field in a model likeAppointment, it would manage the relationship and enforce that the linked object is aDogor aCat, or any other subclass ofAnimalclass you have.Keep your
Animal,Dog,Catmodel class as it is.As said earlier create a new Custom Field I name it as
AnimalGenericForeignKey:This custom field will extend Django's
GenericForeignKeyand include validation to ensure it only points to anAnimalsubclass.Use this custom fields in anywhere you want in your case let's use this in
Appointmentmodel class.Ref. Model ForeignKey limit choices
I hope this will help. In case any questions feel free to ask in comment.