orm多表的创建和基于对象的查询
创建模型
实例:我们来假定下面这些概念,字段和关系
作者模型:一个作者有姓名和年龄。
作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)
出版商模型:出版商有名称,所在城市以及email。
书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。
模型建立如下:
from django.db import models
# Create your models here.
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=32)
age=models.IntegerField()
# 与AuthorDetail建立一对一的关系
authorDetail=models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE)
class AuthorDetail(models.Model):
nid = models.AutoField(primary_key=True)
birthday=models.DateField()
telephone=models.BigIntegerField()
addr=models.CharField( max_length=64)
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=32)
city=models.CharField( max_length=32)
email=models.EmailField()
class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField( max_length=32)
publishDate=models.DateField()
price=models.DecimalField(max_digits=5,decimal_places=2)
# 与Publish建立一对多的关系,外键字段建立在多的一方
publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)
# 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
authors=models.ManyToManyField(to='Author',)
生成表如下:





注意事项:
- 表的名称
myapp_modelName,是根据 模型中的元数据自动生成的,也可以覆写为别的名称 id字段是自动添加的- 对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名
- 这个例子中的
CREATE TABLESQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句。 - 定义好模型之后,你需要告诉Django _使用_这些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加
models.py所在应用的名称。 - 外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。
添加表纪录
操作前先简单的录入一些数据:
publish表:

author表:

authordetail表:

一对多
|
1
2
3
4
5
6
|
方式1: publish_obj=Publish.objects.get(nid=1) book_obj=Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=100,publish=publish_obj) 方式2: book_obj=Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=100,publish_id=1) |
![]()
核心:book_obj.publish与book_obj.publish_id是什么?
多对多
# 当前生成的书籍对象
book_obj=Book.objects.create(title="追风筝的人",price=200,publishDate="2012-11-12",publish_id=1)
# 为书籍绑定的做作者对象
yuan=Author.objects.filter(name="yuan").first() # 在Author表中主键为2的纪录
egon=Author.objects.filter(name="alex").first() # 在Author表中主键为1的纪录
# 绑定多对多关系,即向关系表book_authors中添加纪录
book_obj.authors.add(yuan,egon) # 将某些特定的 model 对象添加到被关联对象集合中。 ======= book_obj.authors.add(*[])
数据库表纪录生成如下:
book表

book_authors表

核心:book_obj.authors.all()是什么?
多对多关系其它常用API:
|
1
2
3
|
book_obj.authors.remove() # 将某个特定的对象从被关联对象集合中去除。 ====== book_obj.authors.remove(*[])book_obj.authors.clear() #清空被关联对象集合book_obj.authors.set() #先清空再设置 |
基于对象的跨表查询
一对多查询(Publish 与 Book)
正向查询(按字段:publish):
|
1
2
3
4
|
# 查询主键为1的书籍的出版社所在的城市book_obj=Book.objects.filter(pk=1).first()# book_obj.publish 是主键为1的书籍对象关联的出版社对象print(book_obj.publish.city) |
反向查询(按表名:book_set):
|
1
2
3
4
5
|
publish=Publish.objects.get(name="苹果出版社")#publish.book_set.all() : 与苹果出版社关联的所有书籍对象集合book_list=publish.book_set.all() for book_obj in book_list: print(book_obj.title) |
一对一查询(Author 与 AuthorDetail)
正向查询(按字段:authorDetail):
|
1
2
|
egon=Author.objects.filter(name="egon").first()print(egon.authorDetail.telephone) |
反向查询(按表名:author):
|
1
2
3
4
5
|
# 查询所有住址在北京的作者的姓名authorDetail_list=AuthorDetail.objects.filter(addr="beijing")for obj in authorDetail_list: print(obj.author.name) |
多对多查询 (Author 与 Book)
正向查询(按字段:authors):
|
1
2
3
4
5
6
|
# 金瓶眉所有作者的名字以及手机号book_obj=Book.objects.filter(title="金瓶眉").first()authors=book_obj.authors.all()for author_obj in authors: print(author_obj.name,author_obj.authorDetail.telephone) |
反向查询(按表名:book_set):
|
1
2
3
4
5
6
|
# 查询egon出过的所有书籍的名字 author_obj=Author.objects.get(name="egon") book_list=author_obj.book_set.all() #与egon作者相关的所有书籍 for book_obj in book_list: print(book_obj.title) |
注意:
你可以通过在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值来覆写 FOO_set 的名称。例如,如果 Article model 中做一下更改:
|
1
|
publish = ForeignKey(Book, related_name='bookList') |
那么接下来就会如我们看到这般:
|
1
2
3
4
|
# 查询 人民出版社出版过的所有书籍publish=Publish.objects.get(name="人民出版社")book_list=publish.bookList.all() # 与人民出版社关联的所有书籍对象集合 |


浙公网安备 33010602011771号