ORM的继承关系,Django中的模型继承www.weide1946.co

2019-05-03 22:33 来源:未知

一、使用最原始的措施继续

O本田UR-VM中国和日本常将目标引用映射到外键,然而对于持续,关周全据库中从未自然使得的办法来对号入座。从数量存款和储蓄的角度来看,在炫人眼目承接关系时,能够应用二种办法(参考JPA中的InheritanceType.定义):

深入Django OENCOREM的接续关系,深切djangoorm承继

O奥迪Q5M中常见将目的引用映射到外键,但是对于持续,关全面据库中未有自然使得的点子来对号入座。从数量存款和储蓄的角度来看,在炫彩承继关系时,能够运用二种办法(参考JPA中的InheritanceType.定义):

Django的O奥迪Q3M也支撑上述三种持续计谋,同时,得益于python的动态天性,还接济代理模型和家家户户承继关系的炫耀。

class Animal(models.Model):
    name = models.CharField(max_length=20)
    age  = models.IntegerField()
class Cat(Animal):
    weight = models.IntegerField()
class Dog(Animal):
    height = models.IntegerField()
  1. 动用单个表,在JPA中称作SINGLE_TABLE。整个承接树共用一张表。使用唯一的表,包蕴全部基类和子类的字段。
  2. 每种具体类一张表,在JPA中称作TABLE_PER_CLASS。那种措施下,每张表都包括具体类和一而再树上全部父类的字段。因为五个表中有再次字段,从任何承接树上来讲,字段是冗余的。
  3. 各样类一张表,承接关系通过表的JOIN操作来代表。在JPA中称作JOINED。那种方法下,每种表只蕴涵类中定义的字段,不设有字段冗余,但是要同时操作子类和有着父类所对应的表。

JOINED映射

借使在Django中完成了Model的持续关系,如下:

www.weide1946.com 1

from django.db import models

class Person(models.Model):
    name = models.CharField(maxlength=10)

class Man(Person):
    job = models.CharField(maxlength=20)

class Woman(Person):
    makeup = models.CharField(maxlength=20)

www.weide1946.com 2

则利用manage.py实践sqlall命令时,会看到那般的结果:

www.weide1946.com 3

CREATE TABLE "uom_person" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(10) NOT NULL
)
;

CREATE TABLE "uom_man" (
"person_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "uom_person" ("id"),
"job" varchar(20) NOT NULL
)
;

CREATE TABLE "uom_woman" (
"person_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "uom_person" ("id"),
"makeup" varchar(20) NOT NULL
)
;

www.weide1946.com 4

可知,Django O君越M中暗中同意使用JOINED格局来贯彻再而三关系的映照。

瞩目:承袭格局不是很合理,父类也会对应一张表。 效用相当的低。

Django的OLX570M也援救上述两种持续计策,同时,得益于python的动态个性,还援救代理模型和名目诸多承袭关系的照射。

TABLE_PER_CLASS映射

借使要兑现各样具体类一张表,只须要将父类钦点为抽象类(abstract),那样就不会创设父类对应的表,而将父类的字段复制到子类中去光彩夺目。如下:

www.weide1946.com 5

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=10)

    class Meta:
        abstract = True

class Man(Person):
    job = models.CharField(max_length=20)

class Woman(Person):
    makeup = models.CharField(max_length=20)

www.weide1946.com 6

sqlall 的结果:

www.weide1946.com 7

CREATE TABLE "uom_man" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(10) NOT NULL,
"job" varchar(20) NOT NULL
)
;

CREATE TABLE "uom_woman" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(10) NOT NULL,
"makeup" varchar(20) NOT NULL
)
;

www.weide1946.com 8

将父类注明为abstract时,该类将尚未objects属性,也正是说未有Manager方法,全数不恐怕举行数量操作,只有子类才具开始展览。

  暗中同意在父类中定义的字段会设有父类表中,子类的多寡经过外键关联父表中数量,子类唯有特殊的数据在子表中。

JOINED映射

要是在Django中实现了Model的接轨关系,如下:

from django.db import models

class Person(models.Model):
    name = models.CharField(maxlength=10)

class Man(Person):
    job = models.CharField(maxlength=20)

class Woman(Person):
    makeup = models.CharField(maxlength=20)

则动用manage.py施行sqlall命令时,会看出这么的结果:

CREATE TABLE "uom_person" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(10) NOT NULL
)
;

CREATE TABLE "uom_man" (
"person_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "uom_person" ("id"),
"job" varchar(20) NOT NULL
)
;

CREATE TABLE "uom_woman" (
"person_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "uom_person" ("id"),
"makeup" varchar(20) NOT NULL
)
;

足见,Django OBMWX三M中暗中同意使用JOINED格局来完毕延续关系的绚烂。

SINGLE_TABLE映射

在TABLE_PER_CLASS的底蕴上,借使进一步内定子类的映照表名与父类的毫无二致,则子类和父类将映射到平等张表,对全体的子类都如此钦赐,就足以兑现SINGLE—_TABLE映射:

www.weide1946.com 9

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=10)
    class Meta:
        abstract = True

class Man(Person):
    job = models.CharField(max_length=20)
    class Meta:
        db_table = 'oum_person'

class Woman(User):
    makeup = models.CharField(max_length=20)

www.weide1946.com 10

sqlall 的结果:

www.weide1946.com 11

CREATE TABLE "oum_person" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(10) NOT NULL,
"job" varchar(20) NOT NULL
)
;

CREATE TABLE "uom_woman" (
"user_ptr_id" integer NOT NULL PRIMARY KEY,
"makeup" varchar(20) NOT NULL
)
;

www.weide1946.com 12

地方的事例中只钦定了3个子类,能够观看因为是在子类上点名,所以Django O奥迪Q伍M更灵敏,能够操纵单个子类的照射格局,从而完成自由的投射结构。

二、Django中的数据库模块提供了一个可怜不易的职能,正是帮助models的面向对象,能够在Meta类中钦点是或不是抽象,然后继续。

TABLE_PER_CLASS映射

假如要达成各个具体类一张表,只须要将父类钦点为抽象类(abstract),那样就不会创制父类对应的表,而将父类的字段复制到子类中去光彩夺目。如下:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=10)

    class Meta:
        abstract = True

class Man(Person):
    job = models.CharField(max_length=20)

class Woman(Person):
    makeup = models.CharField(max_length=20)

sqlall 的结果:

CREATE TABLE "uom_man" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(10) NOT NULL,
"job" varchar(20) NOT NULL
)
;

CREATE TABLE "uom_woman" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(10) NOT NULL,
"makeup" varchar(20) NOT NULL
)
;

将父类注明为abstract时,该类将从未objects属性,也正是说未有Manager方法,全体无法进展数据操作,只有子类才具张开。

代办模型

有如此一种普及的现象:使用一些库(lib)中的类,只是想扩充多数方法,而不想改换其数量存储结构。在Python中,能够经过在Meta类中加进约束proxy=True来落成。此时“子类”称为“父类”的代理类,子类中不得不扩展方法,而不可能扩大属性。举例上边的例子中,假设愿意Person承接Django自带的User类,又不希望破坏User类的数额存款和储蓄,则能够钦赐Person的proxy=True:

www.weide1946.com 13

from django.db import models
from django.contrib.auth.models import User

class Person(User):
#    name = models.CharField(max_length=10)
    class Meta:
        proxy = True

    def do_something(self):
        ...

class Man(Person):
    job = models.CharField(max_length=20)

class Woman(Person):
    makeup = models.CharField(max_length=20)

www.weide1946.com 14

sqlall的结果为:

www.weide1946.com 15

CREATE TABLE "uom_man" (
"user_ptr_id" integer NOT NULL PRIMARY KEY,
"job" varchar(20) NOT NULL
)
;

CREATE TABLE "uom_woman" (
"user_ptr_id" integer NOT NULL PRIMARY KEY,
"makeup" varchar(20) NOT NULL
)
;

www.weide1946.com 16

class Animal(models.Model):
    name = models.CharField(max_length=20)
    age  = models.IntegerField()
    class Meta():
        # 让该类抽象,抽象的父类不会再生产数据表
        # 子类会继承父类中的通用数据,复制到子表中
        abstract = True
class Cat(Animal):
    weight = models.IntegerField()
class Dog(Animal):
    height = models.IntegerField()

SINGLE_TABLE映射

在TABLE_PER_CLASS的底子上,即使越来越钦点子类的映照表名与父类的同样,则子类和父类将映射到同样张表,对持有的子类都如此钦点,就足以兑现SINGLE—_TABLE映射:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=10)
    class Meta:
        abstract = True

class Man(Person):
    job = models.CharField(max_length=20)
    class Meta:
        db_table = 'oum_person'

class Woman(User):
    makeup = models.CharField(max_length=20)

sqlall 的结果:

CREATE TABLE "oum_person" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(10) NOT NULL,
"job" varchar(20) NOT NULL
)
;

CREATE TABLE "uom_woman" (
"user_ptr_id" integer NOT NULL PRIMARY KEY,
"makeup" varchar(20) NOT NULL
)
;

地方的事例中只钦定了八个子类,能够看看因为是在子类上点名,所以Django OQashqaiM更灵敏,可以操纵单个子类的炫人眼目格局,从而达成自由的照射结构。

多种承袭

python扶助多种继承,即使在Model层不推荐使用多种承袭,但Django的OMuranoM依旧帮衬那样的采取办法:

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)

sqlall的结果是:

www.weide1946.com 17

CREATE TABLE "uom_mixin1" (
"id" integer NOT NULL PRIMARY KEY,
"attr1" varchar(10) NOT NULL
)
;

CREATE TABLE "uom_mixin2" (
"id" integer NOT NULL PRIMARY KEY,
"attr1" varchar(10) 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(10) NOT NULL
)
;

www.weide1946.com 18

多种承继的时候,子类的O哈弗M映射会采取第3个父类作为主键管理,其余的父类作为一般的外键管理。

 

代办模型

有那般一种普及的情景:使用一些库(lib)中的类,只是想扩充多数情势,而不想退换其数量存款和储蓄结构。在Python中,能够经过在Meta类中追加约束proxy=True来达成。此时“子类”称为“父类”的代理类,子类中只好扩大方法,而不可能充实品质。比方上边的例子中,若是期望Person承继Django自带的User类,又不指望破坏User类的数目存款和储蓄,则足以钦赐Person的proxy=True:

from django.db import models
from django.contrib.auth.models import User

class Person(User):
#    name = models.CharField(max_length=10)
    class Meta:
        proxy = True

    def do_something(self):
        ...

class Man(Person):
    job = models.CharField(max_length=20)

class Woman(Person):
    makeup = models.CharField(max_length=20)

sqlall的结果为:

CREATE TABLE "uom_man" (
"user_ptr_id" integer NOT NULL PRIMARY KEY,
"job" varchar(20) NOT NULL
)
;

CREATE TABLE "uom_woman" (
"user_ptr_id" integer NOT NULL PRIMARY KEY,
"makeup" varchar(20) NOT NULL
)
;

小结

Django OOdysseyM在炫丽承袭关系时12分灵活,不仅仅可以落到实处JPA约定的SINGLE_TABLE、TABLE_PER_CLASS、JOINED二种艺术,还足以灵活的自定义;乃至经过python的动态语言特征,扶助代理模型和名目多数承袭的功效。可是正因为灵活,所以在应用的时候料定要丰硕专注,通过manage.py的sqllall效率,观看爆发的sql语句,能够表明承袭的实现机制,幸免带来意料之外的主题素材。

OWranglerM的存在延续关系,深入djangoorm承接OPAJEROM中国和扶桑常将对象引用映射到外键,不过对于持续,关全面据库中绝非自然使得的办法来对号入座。从...

多种承袭

python帮助多种承继,固然在Model层不引入应用多种承继,但Django的O中华VM仍然帮衬那样的利用方法:

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)

sqlall的结果是:

CREATE TABLE "uom_mixin1" (
"id" integer NOT NULL PRIMARY KEY,
"attr1" varchar(10) NOT NULL
)
;

CREATE TABLE "uom_mixin2" (
"id" integer NOT NULL PRIMARY KEY,
"attr1" varchar(10) 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(10) NOT NULL
)
;

多种承袭的时候,子类的O奇骏M映射会接纳第一个父类作为主键管理,别的的父类作为一般的外键管理。

小结

Django OTiggoM在酷炫承袭关系时万分灵活,不仅仅能够落到实处JPA约定的SINGLE_TABLE、TABLE_PER_CLASS、JOINED两种艺术,还是能灵活的自定义;以致经过python的动态语言特色,帮助代理模型和三种承继的职能。可是正因为灵活,所以在行使的时候断定要足够注意,通过manage.py的sqllall功用,阅览产生的sql语句,可以证实继承的落成机制,制止带来意想不到的主题素材。

版权声明:本文由韦德娱乐1946_韦德娱乐1946网页版|韦德国际1946官网发布于网络编程,转载请注明出处:ORM的继承关系,Django中的模型继承www.weide1946.co