Polymorphic Model Relations
Django Model Relations — 4
Before learning about this, you may want to take a look at one-to-one, one -to-many and many-to-many relationships.
POLYMORPHIC ONE-TO-MANY RELATIONSHIP
- Sony can be sound system of many car models
- Pioneer can be sound system of many car models
- Car model can have only one sound system (Sony or Pioneer)
|-------------|---------------|
| Car Model | Sound System |
|-------------|---------------|
| C180 | S1 (SONY) |
| C200 | S1 (SONY) |
| X1 | S2 (SONY) |
| A3 | P1 (PIONEER) |
|-------------|---------------|
Add Sony:
$ from modelrelations.models import CarModel, Sony, Pioneer
$ sony1 = Sony.objects.create(name=”Sony Audio System”)
$ sony2 = Sony.objects.create(name=”Sony High Defination Audio System”)$ Sony.objects.all()<QuerySet [
<Sony: Sony Audio System>,
<Sony: Sony High Defination Audio System>
]>
Add Pioneer:
$ pioneer1 = Pioneer.objects.create(name=”Pioneer v1 Audio System”)
$ pioneer2 = Pioneer.objects.create(name=”Pioneer v2 Audio System”)$ Pioneer.objects.all()<QuerySet [
<Pioneer: Pioneer v1 Audio System>,
<Pioneer: Pioneer v2 Audio System>
]>
Associate the CarModel with an Audio System
$ c180 = CarModel.objects.create(name="C180", content_object=sony1)
$ c200 = CarModel.objects.create(name="C200", content_object=sony2)
$ s200 = CarModel.objects.create(name="S200", content_object=sony2)
$ s500 = CarModel.objects.create(name="S500", content_object=pioneer1)$ CarModel.objects.all()<QuerySet [
<CarModel: C180>,
<CarModel: C200>,
<CarModel: S200>,
<CarModel: S500>
]>$ c180.content_object<Sony: Sony Audio System>$ c180.content_object.name'Sony Audio System'
Associate the Audio System with a CarModel
$ sony1.carmodels.all()<QuerySet [
<CarModel: C180>,
]>$ sony2.carmodels.all()<QuerySet [
<CarModel: C200>,
<CarModel: S200>
]>$ pioneer1.carmodels.all()<QuerySet [
<CarModel: S500>
]>$ pioneer2.carmodels.add(c180, s500)
$ pioneer2.carmodels.all()<QuerySet [
<CarModel: C180>,
<CarModel: S500>
]>$ sony1.carmodels.all()<QuerySet []>$ pioneer1.carmodels.all()<QuerySet []>
Clear relations
$ sony2.carmodels.clear()
$ sony2.carmodels.all()<QuerySet []>$ pioneer2.carmodels.clear()
$ pioneer2.carmodels.all()<QuerySet []>
POLYMORPHIC ONE-TO-MANY RELATIONSHIP WITH DJANGO-POLYMORPHIC PACKAGE
Django-polymorphic builds on top of the standard Django model inheritance. It makes using inherited models easier. When a query is made at the base model, the inherited model classes are returned.
First we need to install django-polymorphic package
pip install django-polymorphic
After installation completes, add polymorphic to INSTALLED_APPS:
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'polymorphic',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'modelrelations'
]
Making Your Models Polymorphic
Add Sony
$ from modelrelations.models import CarModel, Sony, Pioneer, Audio
$ sony1 = Sony.objects.create(name=”Sony Audio System”)
$ sony2 = Sony.objects.create(name=”Sony High Defination Audio System”)
Add Pioneer
$ pioneer1 = Pioneer.objects.create(name=”Pioneer v1 Audio System”)
$ pioneer2 = Pioneer.objects.create(name=”Pioneer v2 Audio System”)
List Audio Systems
$ Audio.objects.all()<PolymorphicQuerySet [
<Sony: Sony Audio System>,
<Sony: Sony High Defination Audio System>,
<Pioneer: Pioneer v1 Audio System>,
<Pioneer: Pioneer v2 Audio System>
]>
List Only Sony Audio Systems
$ Audio.objects.instance_of(Sony)<PolymorphicQuerySet [
<Sony: Sony Audio System>,
<Sony: Sony High Defination Audio System>
]>
Select CarModels
$ CarModel.objects.all()<QuerySet [
<CarModel: C180>,
<CarModel: C200>,
<CarModel: S200>,
<CarModel: S500>
]>$ c180 = CarModel.objects.get(id=1)
$ c200 = CarModel.objects.get(id=2)
$ s200 = CarModel.objects.get(id=3)
$ s500 = CarModel.objects.get(id=4)
Associate the Sound System with a CarModel
$ sony1.carmodels.add(c180, c200)
$ pioner1.carmodels.add(s200)$ sony1.carmodel.all()<QuerySet [
<CarModel: C180>,
<CarModel: C200>
]>$ pioneer1.carmodels.all()<QuerySet [
<CarModel: S200>
]>
Associate the CarModel with a Sound System
$ s500.audio = pioneer2
$ s500.save()$ pioneer2.carmodels.all()<QuerySet [
<CarModel: S500>
]>
Clear relations
$ sony2.carmodels.add(c180, c200, s200, s500)
$ sony2.carmodels.all()<QuerySet [
<CarModel: C180>,
<CarModel: C200>,
<CarModel: S200>,
<CarModel: S500>
]>$ sony1.carmodels.all()<QuerySet []>$ pioneer1.carmodels.all()<QuerySet []>$ pioneer2.carmodels.all()<QuerySet []>$ sony2.carmodels.clear()
$ sony2.carmodels.all()<QuerySet []>
POLYMORPHIC MANY-TO-MANY RELATIONSHIP WITH DJANGO-POLYMORPHIC PACKAGE
- 2WD can be drive wheel system of many car models
- 4WD can be drive wheel system of many car models
- Car model can have many drive wheel system (2WD or/and 4WD)
|-------------|---------------|
| Car Model | Drive Wheels |
|-------------|---------------|
| C180 | RWD (2WD) |
| C180 | AWD (4WD) |
| C200 | FWD (2WD) |
| s200 | FWD (2WD) |
| s500 | AWD (4WD) |
|-------------|---------------|
Add Drive System
$ from modelrelations.models import CarModel, Drive, FourWheelDrive, TwoWheelDrive$ rwd = TwoWheelDrive.objects.create(name=”RWD”)
$ fwd = TwoWheelDrive.objects.create(name=”FWD”)$ awd = FourWheelDrive.objects.create(name=”AWD”)$ Drive.objects.all()<PolymorphicQuerySet [
<TwoWheelDrive: RWD>,
<TwoWheelDrive: FWD>,
<FourWheelDrive: AWD>
]>
Select CarModels
$ CarModel.objects.all()<QuerySet [
<CarModel: C180>,
<CarModel: C200>,
<CarModel: S200>,
<CarModel: S500>]>
$ c180 = CarModel.objects.get(id=1)
$ c200 = CarModel.objects.get(id=2)
$ s200 = CarModel.objects.get(id=3)
$ s500 = CarModel.objects.get(id=4)
Associate the CarModel with a Drive
$ c180.drive.add(rwd, awd)
$ c180.drive.all()<PolymorphicQuerySet [
<TwoWheelDrive: RWD>,
<FourWheelDrive: AWD>
]>$ s500.drive.add(awd, fwd, rwd)<PolymorphicQuerySet [
<TwoWheelDrive: RWD>,
<TwoWheelDrive: FWD>,
<FourWheelDrive: AWD>
]>
Associate the Drive with a CarModel
$ fwd.carmodels.add(s200, c200)
$ fwd.carmodels.all()<QuerySet [
<CarModel: C200>,
<CarModel: S200>,
<CarModel: S500>
]>
Removing Drive from a CarModel:
$ s500.drive.remove(fwd)
$ s500.drive.all()<PolymorphicQuerySet [
<TwoWheelDrive: RWD>,
<FourWheelDrive: AWD>
]>
Relation sets can be set:
$ s500.drive.set([awd])
$ s500.drive.all()<PolymorphicQuerySet [
<FourWheelDrive: AWD>
]>
Relation sets can be cleared:
$ s500.drive.clear()
$ s500.drive.all()<PolymorphicQuerySet []>
For more information about Polymorphism in Django you can check :
If you want to learn more about Django, do check out the documentation, and make sure to check out our articles!