设为首页 加入收藏

TOP

Django学习之十四:Django ORM继承关系(一)
2019-07-15 18:09:53 】 浏览:132
Tags:Django 习之 十四 ORM 继承 关系

Django ORM继承关系

参考:https://www.cnblogs.com/holbrook/archive/2012/03/18/2405036.html

     因为关系数据库是没有自然有效的方法来表示表与表之间的继承关系。而model layer 是用类来表示表,而类是面向对象的范畴,继承是它的一大特性。自然可以使用model class 通过继承来表示它们之间的关系,但是要映射到关系数据库应该是怎样表示。这就得从数据库存储的角度来看,大牛们采用了几种在数据库中映射继承关系的方式:主要三种
single_table/table_per_class/joined 主要三种
由于python语言的动态性,python类是可以进行多重继承关系,那么还有多重继承关系的映射。
最后还有一种代理模型继承。

    对于抽象model的定义,必须在其内嵌类中指定一个abstract = True的metadata,需要注意的是,虽然subclass继承了抽象类,同时继承了class meta内嵌类的内容;但是有些内嵌类中的属性是不会被继承的,如对于abstract = True 这个metadata是没有继承的。也就是说在构建subclass 的时候,会将abstract 设置为Flase。如果要构建一个抽象类继承自一个抽象类, 那么就需要在子抽象类中显示的声明abstract = True。相同的如db_table也不会继承到子类中,子类需要自己声明。

因为orm的可继承和三种继承方式的特点,那么一个model映射一个数据库表的说法就错了。抽象model是不会映射任何数据库表的。

1. SINGLE_TABLE(django好像不支持)

使用单个表,且数据库中只有一个映射表,这个表就代表了整个继承树,继承树中的多个子类model只会操作自己新增的字段,不会因为整个继承树使用一个表而能操作其它非自己的字段;这种就是一表收揽所有字段,字段虽然没有冗余了,但是数据父类数据对象是冗余的。同一个父对象有多个子对象。
single_table 在model layer上定义就是父类和子类

from django.db import models

class Vehicle(models.Model): # 抽象类在migration时不会创建表
    name = models.CharField(max_length=32)

    class Meta:
        abstract = True

class Car(Vehicle):
    Color = models.CharField(max_length=32)

    class Meta:
        db_table = 'mbook_vehicle'

class Bike(Vehicle):
    Weight = models.IntegerField()

    class Meta:
        db_table = 'mbook_vehicle'
    

2. TABLE_PER_CLASS

有字段冗余,每个类一张表,父类是抽象类不创建父类映射的表,而是将父类的字段复制到子类映射表中去。

from django.db import models

class Animal(models.Model):
    name = models.CharField(max_length=32)

    class Meta:
        abstract = True

class Dog(Animal):
    Color = models.CharField(max_length=32)

class Bird(Animal):
    Size = models.CharField(max_length=32)

使用python manage.py sqlmigrate mbook 0005 查看sql如下:

BEGIN;
--
-- Create model Bird
--
CREATE TABLE `mbook_bird` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(32) NOT NULL, `Size` varchar(32) NOT NULL);
--
-- Create model Dog
--
CREATE TABLE `mbook_dog` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(32) NOT NULL, `Color` varchar(32) NOT NULL);
COMMIT;
-- 只创建了具体类表,抽象父类是没有创建的。并且name字段是冗余的。

因为Animal类是抽象类,所以没有objects属性,即没有manager管理器,所以不能操作数据对象,映射表也没创建,自然也不能操作数据。只有子类才能操作。

抽象继承操作没什么说的,就是操作继承的具体子类就可以了。这个是用的比较多的。

3. JOINED

没有冗余,每个类一张表,要同时操作父表和子表

from django.db import models

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

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

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

使用python manage.py sqlmigrate mbook 0004 可以看到创建表的sql语句

BEGIN;
--
-- Create model Person
--
CREATE TABLE `mbook_person` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(32) NOT NULL);  -- id是django自动生成的
--
-- Create model Man
--
CREATE TABLE `mbook_man` (`person_ptr_id` integer NOT NULL PRIMARY KEY, `job` varchar(32) NOT NULL);
--
-- Create model Woman
--
CREATE TABLE `mbook_woman` (`person_ptr_id` integer NOT NULL PRIMARY KEY, `makeup` varchar(32) NOT NULL);

ALTER TABLE `mbook_man` ADD CONSTRAINT `mbook_man_person_ptr_id_9ab049ad_fk_mbook_person_id` FOREIGN KEY (`person_ptr_id`) REFERENCES `mbook_person` (`id`);
-- 添加一个外键
ALTER TABLE `mbook_woman` ADD CONSTRAINT `mbook_woma
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇学习8.内容#文件操作 读 写 加 下一篇用Python递归做个多层次的文件执行

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目