ForeignKey field associated with an abstract model in Django

I have this model:

class BaseModel(models.Model): .... class Meta: abstract = True class ModelA(BaseModel): .... class ModelB(BaseModel): .... class MyExtModel(models.Model) myfield = models.ForeignKey(BaseModel) 

But this is not true, because I have BaseModel as Abstract . Infact I have an error while trying to execute the makemigration command.

Mistake:

 ERRORS: myapp.MyExtModel.myfield: (fields.E300) Field defines a relation with model 'BaseModel', which is either not installed, or is abstract. 

Is there a way to use an abstract base model?

I also tried using:

 myfield = models.ForeignKey(BaseModel, related_name="%(app_label)s_%(class)s_related") 
+7
python django abstract foreign-keys
source share
3 answers

Unable to set foreign keys for abstract models in Django. However, you can set foreign keys for a non-abstract base class. The only limitation is that the inverse relationship of the foreign key will return instances of the base class. You can get around this limitation using django-polymorphic .

Django Polymorphic allows you to query objects of the base class, but retrieves instances of the child class:

 >>> Project.objects.create(topic="Department Party") >>> ArtProject.objects.create(topic="Painting with Tim", artist="T. Turner") >>> ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter") >>> Project.objects.all() [ <Project: id 1, topic "Department Party">, <ArtProject: id 2, topic "Painting with Tim", artist "T. Turner">, <ResearchProject: id 3, topic "Swallow Aerodynamics", supervisor "Dr. Winter"> ] 

To use polymorphic django, you only need to declare your models using the Polymorphic model as a base class:

 from django.db import models from polymorphic.models import PolymorphicModel class ModelA(PolymorphicModel): field1 = models.CharField(max_length=10) class ModelB(ModelA): field2 = models.CharField(max_length=10) class ModelC(ModelB): field3 = models.CharField(max_length=10) 

Foreign keys also return instances of the child classes that you need. I suppose:

 # The model holding the relation may be any kind of model, polymorphic or not class RelatingModel(models.Model): many2many = models.ManyToManyField('ModelA') # ManyToMany relation to a polymorphic model >>> o=RelatingModel.objects.create() >>> o.many2many.add(ModelA.objects.get(id=1)) >>> o.many2many.add(ModelB.objects.get(id=2)) >>> o.many2many.add(ModelC.objects.get(id=3)) >>> o.many2many.all() [ <ModelA: id 1, field1 (CharField)>, <ModelB: id 2, field1 (CharField), field2 (CharField)>, <ModelC: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ] 

Please note that these queries will be slightly less effective .

+6
source share

When I came across a situation where I need to make ForeignKeys for different models, I prefer to use GenericForeignKey , you can check the official docs here: Django ContentTypes: General relationship

The docs pretty well explain how to use it:

 from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType class TaggedItem(models.Model): tag = models.SlugField() content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') def __str__(self): # __unicode__ on Python 2 return self.tag 
  • A model is stored in the content_type field in which the shared foreign key points to

  • The foreign key identifier is stored in the object_id field,

  • The content_object field allows you to directly access the related object based on the other 2 fields

This is not the best solution, but it saves me in some projects

Usage example:

 from django.contrib.auth.models import User guido = User.objects.get(username='Guido') t = TaggedItem(content_object=guido, tag='bdfl') t.save() t.content_object <User: Guido> 
+3
source share

Besides a nice answer with a GenericForeignKey that I am not completely familiar with, sometimes (sometimes when possible), he pays to simplify your models using a one-to-one relationship with your β€œbase” model.

After that, it simplifies the management of foreign keys. If I remember well, a foreign key in an abstract class is not possible.

+1
source share

All Articles