今天看到一篇關于介紹Django繼承機制的帖子,雖然簡單,但是還是記下來,以免忘記:
django 的繼承有兩種方式:
第一種:將父類聲明為abstract,這樣每個具體的子類均有一個對應的表,父類是抽象類,不會為之建表
from django.db import models

# Create your models here.
class Person(models.Model):
name = models.CharField(max_length=10)
height = models.SmallIntegerField()
class Meta:
abstract=True

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


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

通過在Meta類中聲明abstract=True,標識Person為抽象基類,這個類沒有objects屬性,也就是說沒有Manager方法,無法進行單獨的數據操作,所有的數據操作都要通過子類進行
生成的sql語句如下
BEGIN;
CREATE TABLE `sample_woman` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(10) NOT NULL,
`height` smallint NOT NULL,
`makeup` varchar(20) NOT NULL
)
;
CREATE TABLE `sample_man` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(10) NOT NULL,
`height` smallint NOT NULL,
`job` varchar(20) NOT NULL
)
;
COMMIT;
第二種:
基類一個表,每個子類的擴展屬性另一個表,寫法上沒有什么特別要求
from django.db import models

# Create your models here.
class Person(models.Model):
name = models.CharField(max_length=10)
height = models.SmallIntegerField()


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


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

生成的sql如下
BEGIN;
CREATE TABLE `sample_person` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(10) NOT NULL,
`height` smallint NOT NULL
)
;
CREATE TABLE `sample_woman` (
`person_ptr_id` integer NOT NULL UNIQUE PRIMARY KEY,
`makeup` varchar(20) NOT NULL
)
;
ALTER TABLE `sample_woman` ADD CONSTRAINT person_ptr_id_refs_id_4baa7c33 FOREIGN
KEY (`person_ptr_id`) REFERENCES `sample_person` (`id`);
CREATE TABLE `sample_man` (
`person_ptr_id` integer NOT NULL UNIQUE PRIMARY KEY,
`job` varchar(20) NOT NULL
)
;
ALTER TABLE `sample_man` ADD CONSTRAINT person_ptr_id_refs_id_78ed52db FOREIGN K
EY (`person_ptr_id`) REFERENCES `sample_person` (`id`);
CREATE UNIQUE INDEX `sample_woman_person_ptr_id` ON `sample_woman` (`person_ptr_
id`);
CREATE UNIQUE INDEX `sample_man_person_ptr_id` ON `sample_man` (`person_ptr_id`)
;
COMMIT;
Person類可以進行數據查詢操作,所以有必要識別返回的類是什么的問題,這里isinstance沒用,django的處理是為Person添加子類的屬性,以方便你通過這些屬性訪問具體的子類,在這里
results=Person.objects.all()
r=results[0]
這個r就有woman和man兩個屬性,下面的結論摘自我在郵件列表中的答復,備忘用
這時,person_obj有 man和person兩個屬性
如果訪問一個不是屬于該類型的就會出現DoesNotExist 異常
實際中,不用通過捕獲異常去判斷,直接用
hasattr(person_obj,'man') 或 hasattr(person_obj,'woman') 就可以判斷,返回True的就是
目標類型

(InteractiveConsole)


>>> from sample.models import *
>>> results=Person.objects.all()
>>> r=results[0]
>>> hasattr(r,'woman')
False
>>> hasattr(r,'man')
True
>>> r.man.job
u'computer'
>>> r.woman


Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:"Python25"Lib"site-packages"django"db"models"fields
"related.py", line
178, in __get__
rel_obj = self.related.model._default_manager.get(**params)
File "C:"Python25"Lib"site-packages"django"db"models"manager.py",
line 82, in
get
return self.get_query_set().get(*args, **kwargs)
File "C:"Python25"Lib"site-packages"django"db"models"query.py", line
197, in g
et
% self.model._meta.object_name)
DoesNotExist: Woman matching query does not exist.

