一.创建模型
作者模型:一个作者有姓名和年龄。
作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)
出版商模型:出版商有名称,所在城市以及email。
书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。
表与表之间的关系 1 一对多 单表操作: class Book(models.Model): title=models.CharField(max_length=32) publish=models.CharField(max_length=32) publish_email=models.CharField(max_length=32) publish_addr=models.CharField(max_length=32) Book title publish_name publish_email publish_addr python 人民出版社 123 beijing linux 人民出版社 123 beijing go 人民出版社 123 beijing ##################### Book title publish_id python 1 go 1 Publish id name addr email 1 人民出版社 beijing 123 2 北京出版社 beijing 234 KEY: 必须在"多"的表中创建关联字段,外加约束 ''' create table book( title varchar(30), publish_id INT, foreignKey publish_id references Publish(id) ) ''' 2 一对一 Author name age ad_id(唯一约束) alex 12 1 egon 23 1 AuthorDetail id gender tel gf addr 1 male 110 铁锤 山东 2 male 991 钢弹 山东 KEY:在任意表中加关联字段,唯一约束 3 多对多 Book id title publish_id 1 python 1 2 go 1 Author id name age ad_id(唯一约束) 1 alex 12 1 KEY:创建第三张表 Book2Author id book_id author_id 1 1 1 2 1 2 3 2 2
模型创建:
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 TABLE
SQL 语句使用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) |
####### 一对多 ########## ''' 正向查询:关联属性所在的表查询关联表记录 反向查询 ----正向查询按字段:book.publish Book------------------------------------>Publish <----------------------------------- 反向查询表名小写_set.all():pub_obj.book_set.all() ''' #1 查询python这本书出版社的名字和邮箱 book=Book.objects.filter(title="python").first() pub_obj=Publish.objects.filter(nid=book.publish_id).first()print(pub_obj.name)print(pub_obj.email) ######################## book = Book.objects.filter(title="python").first()print(book.publish) # 与book这本书关联出版社对象 print(book.publish.name) # 与book这本书关联出版社对象print(book.publish.email) # 与book这本书关联出版社对象 # 2 查询苹果出版社出版的所有的书籍的名称 # pub_obj=Publish.objects.get(name="苹果出版社") # print(pub_obj.book_set.all()) # queryset # print(pub_obj.book_set.all().values("title")) # queryset
一对一查询(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) |
####### 一对一 ########## ''' 正常查询安字段:alex.ad Author -----------------------------------------> AuthorDetail <------------------------------------------ 反向查询按表名小写 ad.author ''' # 查询alex的手机号 alex = Author.objects.filter(name="alex").first() print(alex.ad.tel) # 查询手机号为110的作者的名字 ad=AuthorDetail.objects.filter(tel=110).first() print(ad.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) |
####### 多对多 ########## ''' 正向查询按字段 book.authors.all() Book -------------------------------------->Author <-------------------------------------- 反向查询按表名小写_set.all(): alex.book_set.all() ''' # 查询python这本书籍的作者的年龄 book=Book.objects.filter(title="python").first() ret=book.authors.all().values("age") # 与这本书关联的左右作者的queryset的集合 print(ret) #查询alex出版过的所有的书籍名称 alex=Author.objects.filter(name="alex").first() print(alex.book_set.all())
注意:
你可以通过在 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 () # 与人民出版社关联的所有书籍对象集合 |