In-depth Django ORM inheritance relationships

Source: Internet
Author: User

An ORM typically maps an object reference to a foreign key, but for inheritance, there is no natural and efficient way to correspond to a relational database. From the point of view of data storage, there are several ways to map an inheritance relationship (refer to the Inheritancetype. Definition in JPA):

  1. Use a single table, called Single_table in JPA. The entire inheritance tree is shared with a single table. Use a unique table that contains the fields for all base classes and subclasses.
  2. Each concrete class is a table, called Table_per_class in JPA. In this way, each table contains the fields of the concrete class and all the parent classes on the inheritance tree. Because there are repeating fields in multiple tables, the fields are redundant from the entire inheritance tree.
  3. Each class is a table, and the inheritance relationship is represented by a JOIN operation on the table. Called joined in JPA. In this way, each table contains only the fields defined in the class, there is no field redundancy, but you want to manipulate the tables for both the child class and all the parent classes.

The Django Orm also supports the three inheritance strategies mentioned above, and also supports the mapping of proxy models and multiple inheritance relationships thanks to the dynamic nature of Python.

Joined mapping

If the model inheritance is implemented in Django, the following is true:

 from Import Models

class Person (models. Model):
Name = models. Charfield (maxlength=10)

class Man:
Job = models. Charfield (MAXLENGTH=20)

class Woman (person):
Makeup = models. Charfield (MAXLENGTH=20)

When you execute the sqlall command with manage.py, you see the result:

CREATE TABLE"Uom_person" (
"id"integer not NULL PRIMARY KEY,
"Name"varchar(Ten) not NULL
)
;

CREATE TABLE"Uom_man" (
"PERSON_PTR_ID"integer not NULL PRIMARY KEY REFERENCES"Uom_person" ("id"),
"Job"varchar( -) not NULL
)
;

CREATE TABLE"Uom_woman" (
"PERSON_PTR_ID"integer not NULL PRIMARY KEY REFERENCES"Uom_person" ("id"),
"Makeup"varchar( -) not NULL
)
;

As you can see, the joined method is used by default in Django ORM to implement mappings for inheritance relationships.

Table_per_class Mapping

If you want to implement a table for each specific class, you only need to specify the parent class as an abstract class (abstract) so that the table for the parent class is not created and the field of the parent class is copied to the subclass to map. As follows:

 from Import Models

class Person (models. Model):
Name = models. Charfield (max_length=10)

class Meta:
abstract = True

class Man:
Job = models. Charfield (MAX_LENGTH=20)

class Woman (person):
Makeup = models. Charfield (MAX_LENGTH=20)

Results of Sqlall:

CREATE TABLE"Uom_man" (
"id"integer not NULL PRIMARY KEY,
"Name"varchar(Ten) not NULL,
"Job"varchar( -) not NULL
)
;

CREATE TABLE"Uom_woman" (
"id"integer not NULL PRIMARY KEY,
"Name"varchar(Ten) not NULL,
"Makeup"varchar( -) not NULL
)
;

When the parent class is declared abstract, the class will not have the objects property, that is, there is no manager method, all data operations cannot be performed, only subclasses can do it.

Single_table Mapping

On the basis of table_per_class, if you further specify that the mapping table name of the subclass is the same as the parent class, then the child class and the parent class are mapped to the same table and all subclasses are specified so that the single-_table mapping can be implemented:

 from Import Models

class Person (models. Model):
Name = models. Charfield (max_length=10)
class Meta:
abstract = True

class Man:
Job = models. Charfield (MAX_LENGTH=20)
class Meta:
' Oum_person '

class Woman (User):
Makeup = models. Charfield (MAX_LENGTH=20)

Results of Sqlall:

CREATE TABLE"Oum_person" (
"id"integer not NULL PRIMARY KEY,
"Name"varchar(Ten) not NULL,
"Job"varchar( -) not NULL
)
;

CREATE TABLE"Uom_woman" (
"USER_PTR_ID"integer not NULL PRIMARY KEY,
"Makeup"varchar( -) not NULL
)
;

The above example specifies only one subclass, which can be seen as being specified on a subclass, so the Django Orm is more flexible and can control the mapping of individual subclasses to implement arbitrary mapping structures.

Proxy model

There is a common scenario: using classes in some library (Lib), just want to extend some methods rather than change their data storage structure. In Python, you can do this by adding a constraint proxy=true to the Meta class. In this case, the subclass is called the proxy class of the parent class, and only the methods can be added to the subclass, not the attributes. For example, if you want a person to inherit the user class from Django, and you do not want to break the data store of the user class, you can specify the proxy=true of the person:

 from Import Models
from Import User

class Person (User):
# name = models. Charfield (max_length=10)
class Meta:
Proxy = True

def do_something (self):
...

class Man:
Job = models. Charfield (MAX_LENGTH=20)

class Woman (person):
Makeup = models. Charfield (MAX_LENGTH=20)

The results of the Sqlall are:

CREATE TABLE"Uom_man" (
"USER_PTR_ID"integer not NULL PRIMARY KEY,
"Job"varchar( -) not NULL
)
;

CREATE TABLE"Uom_woman" (
"USER_PTR_ID"integer not NULL PRIMARY KEY,
"Makeup"varchar( -) not NULL
)
;
Multiple inheritance

Python supports multiple inheritance, although it is not recommended to use multiple inheritance at the model level, but Django's ORM supports the use of this method:

class Mixin1 (models. Model):
ATTR1 = models. Charfield (max_length=10)
class Mixin2 (models. Model):
ATTR1 = models. Charfield (max_length=10)
class Multiple (mixin1,mixin2):
ATTR3 = models. Charfield (max_length=10)

The result of Sqlall is:

CREATE TABLE"Uom_mixin1" (
"id"integer not NULL PRIMARY KEY,
"Attr1"varchar(Ten) not NULL
)
;

CREATE TABLE"Uom_mixin2" (
"id"integer not NULL PRIMARY KEY,
"Attr1"varchar(Ten) not NULL
)
;

CREATE TABLE"Uom_multiple" (
"MIXIN2_PTR_ID"integer not NULL UNIQUE REFERENCES"Uom_mixin2" ("id"),
"MIXIN1_PTR_ID"integer not NULL PRIMARY KEY REFERENCES"Uom_mixin1" ("id"),
"ATTR3"varchar(Ten) not NULL
)
;

When multiple inheritance occurs, the ORM mapping of a subclass chooses the first parent class as the primary key management, and the other parent class as the general foreign Key management.

Summary

Django ORM is very flexible in mapping inheritance relationships, not only to implement the JPA conventions of Single_table, Table_per_class, joined three ways, but also flexible customization, even through the dynamic language characteristics of Python, Supports the proxy model and multiple inheritance features. But because of flexibility, so in the use of the time must be very careful, through the manage.py sqllall function, observe the resulting SQL statement, you can verify the implementation of the inheritance mechanism, to avoid unexpected problems.

Go deep into the Django Orm inheritance relationship

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.