一,创建表
我们首先创建图书管理系统有关的表,其中包括书籍表 , 作者表 , 出版社表 , 作者详情表
作者与作者详情是一对一的关系
书籍与出版社是一对多,多对一的关系
书籍与作者是多对多的关系, 由于在数据库中多对多需要第三张表来记录他们之间的关系, 但是Django的orm会自动帮我们创建好对应的第三张表,只需要把多对多的对应关系在创建书籍与作者表的时候写好就可以了.
from django.db import models # Create your models here. 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建立一对多的关系,外键字段建立在多的一方,orm会在我们publish字段中自动拼接publish的id字段(publish_id) #'to=':要关联的表 , 'to_field':关联的字段 ,'on_delete=models.CASCADE':同步删除 publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE) # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表 authors=models.ManyToManyField(to='Author',) 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()
然后根据上篇博客中关于创建表的各种操作进行配置好后,同步一下
接下来去数据库中对应看一下创建好的表格
我们自己创建了book ,publish, author, authordetail 四张表,还有一张book_authors表时orm根据我们设置的book与author表多对多的关系帮我们创建的
对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名,例如book表中的publish_id字段
外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。
二,创建表记录
(1), 一对多的添加方式
#方式一 publish_obj=Publish.objects.get(nid=1) book_obj=Book.objects.create(title="python",publishDate="2012-12-12",price=100,publish=publish_obj) #方式二 book_obj=Book.objects.create(title="python",publishDate="2012-12-12",price=100,publish_id=1) #区别在于是否直接把publish_id直接写好,其实是一样的
(2), 多对多的添加方式
#先找到作者对象 yuan=Author.objects.filter(name="yuan").first() # 在Author表中主键为2的纪录 egon=Author.objects.filter(name="alex").first() # 在Author表中主键为1的纪录 ###############关系绑定#################### #方式一 book.authors.add(alex,egon) #方式二 book.authors.add(1,2) #方式三 book.authors.add(*[1,2]) #############关系解除####################### book = Book.objects.filter(nid=3).first() book.authors.clear() #清空所有内容 book.authors.add(1) #添加一个nid为3,author_id为1的内容 book.authors.set(1) #重置 book.authors.remove(1) #删除nid为3,author_id为1的
三,查询
正向查询: 关联属性所在的表,查询关联的表,按字段查
反向查询: 关联表查询关联属性所在的表,按表名小写_set.all() (如果是一对一,只能查到一条的话,就不需要加'_set.all()')
基于对象的跨表查询
(1) 一对多查询
正向查询 : 按字段
# 查询python这本书出版社的名字和邮箱 pub_obj=Publish.objects.filter(nid=book.publish_id).first() print(pub_obj.name) print(pub_obj.email)
反向查询 : 按表名小写_set.all()
#查询苹果出版社出版的所有的书籍的名称 pub_obj=Publish.objects.get(name="苹果出版社") print(pub_obj.book_set.all().values("title"))
(2),多对多
正向查询 : 按字段
# 查询python这本书籍的作者的年龄 book=Book.objects.filter(title="python").first() ret=book.authors.all().values("age") # 与这本书关联的左右作者的queryset的集合 print(ret)
反向查询 : 按表名小写_set.all()
#查询alex出版过的所有的书籍名称 alex=Author.objects.filter(name="alex").first() print(alex.book_set.all())
(3) , 一对一
正向查询 : 按字段
# 查询alex的手机号 alex = Author.objects.filter(name="alex").first() print(alex.ad.tel)
反向查询 : 按表名小写
# 查询手机号为110的作者的名字 ad=AuthorDetail.objects.filter(tel=110).first() print(ad.author.name)
基于双下划线的跨表查询
(1),一对多查询
查询alex出过的所有书籍的名字(多对多)
正向查询 : 按字段
queryResult=Book.objects .filter(publish__name="苹果出版社") .values_list("title","price")
反向查询按表名小写
queryResult=Publish.objects .filter(name="苹果出版社") .values_list("book__title","book__price")
(2),多对多查询
查询alex的手机号
# 正向查询 ret=Author.objects.filter(name="alex").values("authordetail__telephone") # 反向查询 ret=AuthorDetail.objects.filter(author__name="alex").values("telephone")
(3),连续跨表
练习: 查询人民出版社出版过的所有书籍的名字以及作者的姓名 # 正向查询 queryResult=Book.objects .filter(publish__name="人民出版社") .values_list("title","authors__name") # 反向查询 queryResult=Publish.objects .filter(name="人民出版社") .values_list("book__title","book__authors__age","book__authors__name") # 练习: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称 # 方式1: queryResult=Book.objects .filter(authors__authorDetail__telephone__regex="151") .values_list("title","publish__name") # 方式2: ret=Author.objects .filter(authordetail__telephone__startswith="151") .values("book__title","book__publish__name")
聚合查询与分组查询
(1) 聚合
from
django.db.models
import
Avg,
Max
,
Min
,Count
Book.objects.aggregate(average_price=Avg('price')) {'average_price': 34.35}
(2),分组
.valuse(按照什么分组).annotate(放聚合函数).valuse(要显示的内容)
F与Q查询
Django 提供 F() 来做两个字段的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
from django.db.models import F Book.objects.filter(commnetNum__lt=F('keepNum')) Book.objects.filter(commnetNum__lt=F('keepNum')*2) #将每一本书的价格提高三十元 Book.objects.all().update(price=F("price")+30)
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象
& : and
| :或
~ :取反
bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017), title__icontains="python" )