数据模型的定义同样遵循python类的继承,介绍以下几种定义方式:

  • 使用单个表。整个继承树共用一张表。使用唯一的表,包含所有基类和子类的字段。

  • 每个具体类一张表,这种方式下,每张表都包含具体类和继承树上所有父类的字段。因为多个表中有重复字段,从整个继承树上来说,字段是冗余的。

  • 每个类一张表,继承关系通过表的JOIN操作来表示。这种方式下,每个表只包含类中定义的字段,不存在字段冗余,但是要同时操作子类和所有父类所对应的表。

方式一:每个类一张表
from django.db import models
 
class Person(models.Model):
  name = models.CharField(max_length=20)
  sex = models.BooleanField(default=True)
 
class teacher(Person):
  subject = models.CharField(max_length=20)
 
class student(Person):
  course = models.CharField(max_length=20)

 执行:python manage.py sqlall

BEGIN;
CREATE TABLE "blog_person" (
    "id" integer NOT NULL PRIMARY KEY,
    "name" varchar(20) NOT NULL,
    "sex" bool NOT NULL
)
;
CREATE TABLE "blog_teacher" (
    "person_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "blog_person" ("id"),
    "subject" varchar(20) NOT NULL
)
;
CREATE TABLE "blog_student" (
    "person_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "blog_person" ("id"),
    "course" varchar(20) NOT NULL
)
;
 
COMMIT;

方式二:每个具体类一张表,父类不需要创建表
from django.db import models
 
class Person(models.Model):
  name = models.CharField(max_length=20)
  sex = models.BooleanField(default=True)
 
  class Meta:
    abstract = True
 
class teacher(Person):
  subject = models.CharField(max_length=20)
 
class student(Person):
  course = models.CharField(max_length=20)

 执行:python manage.py sqlall

BEGIN;
CREATE TABLE "blog_teacher" (
    "id" integer NOT NULL PRIMARY KEY,
    "name" varchar(20) NOT NULL,
    "sex" bool NOT NULL,
    "subject" varchar(20) NOT NULL
)
;
CREATE TABLE "blog_student" (
    "id" integer NOT NULL PRIMARY KEY,
    "name" varchar(20) NOT NULL,
    "sex" bool NOT NULL,
    "course" varchar(20) NOT NULL
)
;
 
COMMIT;

 方式三:自定义创建的表名
from django.db import models
 
class Person(models.Model):
  name = models.CharField(max_length=20)
  sex = models.BooleanField(default=True)
 
  class Meta:
    abstract = True
 
class teacher(Person):
  subject = models.CharField(max_length=20)
 
  class Meta:
    db_table = "Teacher"
 
class student(Person):
  course = models.CharField(max_length=20)
 
  class Meta:
    db_table = "Student"

 执行:python manage.py sqlall

BEGIN;
CREATE TABLE "Teacher" (
    "id" integer NOT NULL PRIMARY KEY,
    "name" varchar(20) NOT NULL,
    "sex" bool NOT NULL,
    "subject" varchar(20) NOT NULL
)
;
CREATE TABLE "Student" (
    "id" integer NOT NULL PRIMARY KEY,
    "name" varchar(20) NOT NULL,
    "sex" bool NOT NULL,
    "course" varchar(20) NOT NULL
)
;
 
COMMIT;

方式四:代理模型,为子类增加方法,但不能增加属性
from django.db import models
 
class Person(User):
  class Meta:
    proxy = True
 
  def some_function(self):
    ……

这样的方式不会改变数据存储结构,但可以纵向的扩展子类Person的方法,并且基础User父类的所有属性和方法。

方式五:通过子类增加属性,例如要利用django的User类,但是我们还需要额外增加一些字段,但有不想去破坏原生自带的User类,就可以通过以下方法去实现
from django.contrib.auth.models import User
from django.db import models
 
class Person(models.Model):
  user = models.OneToOneField(User)
 
  blog = models.CharField(max_length=100)
  location = models.CharField(max_length=200)