Django - 模型层 - 多表
阅读目录
一、多表 sql
一对多
Book
id title price publish email addr
1 php 100 人民出版社 111 北京
2 python 120 沙河出版社 222 沙河
3 go 110 人民出版社 119 北京
4 java 300 人民出版社 111 北京
Book多
id title price publish_id
1 php 100 1
2 python 120 1
3 go 110 2
4 java 300 1
Publish一
id name email addr
1 人民出版社 111 北京
2 沙河出版社 222 沙河
查询python这本书的出版社的邮箱(子查询)
select publish_id from Book where title="python"
select email from Publish where id=1 id=(上边的)
一旦确定是一对多的表关系:建立一对多的关系------->在多的表中建立关联字段(publish_id)
######################################################################
多对多:
Book
id title price publish_id
1 php 100 1
2 python 120 1
3 go 110 2
4 java 300 1
Author
id name age addr
1 alex 34 北京
2 egon 55 南京Book2Author
id book_id author_id
1 2 1
2 2 2
3 3 2
alex出版过的书籍名称(子查询)
select id form Author where name='alex' (拿到alex这个id)
select book_id from Book2Author where author_id=1
select title from Book id=book_id
一旦确定表关系是多对多:创建第三张表:
id book_id author_id######################################################################
一对一:
Author
id name age Authordetail_id(unique)
1 alex 34 1
2 egon 55 2
AuthorDetail
id addr gender tel gf_name
1 北京 male 110 小花
2 南京 male 911 小红######################################################################
一旦确定是一对多的关系:建立一对多的关系------->在多的表中建立关联字段 (一个出版社可以出版多本书)
一旦确定多对多的关系:建立多对多的关系--------->创建第三张表(关联表):id和两个关联字段 (一本书可以有多个作者,一个作者可以出版多本书;)
一旦确定一对一的关系:建立一对一的关系---------->在两张表中的任意一张表中建立关联字段+unique (一个作者只有一个详细信息)######################################################################
Publish
Book
Author
AuthorDetail
Book2Author对应的sql语句
######################################################################
CREATE TABLE publish(
id INT PRIMARY KEY auto_increment,
name VARCHAR(20)
);CREATE TABLE book(
id INT PRIMARY KEY auto_increment,
title VARCHAR (20),
price DECIMAL (8,2),
pub_date DATE,
publish_id INT,
FOREIGN KEY (publish_id) REFERENCES publish(id) 一个出版社可以出版多本书
);CREATE TABLE authordetail(
id INT PRIMARY KEY auto_increment,
tel VARCHAR(20)
);
CREATE TABLE author(
id INT PRIMARY KEY auto_increment,
name VARCHAR(20),
age INT,
authordetail_id INT UNIQUE,
FOREIGN KEY(authordetail_id) REFERENCES authordetail(id) 一个作者只有一个详细信息
);
CREATE TABLE book2author(
id INT PRIMARY KEY auto_increment,
book_id INT,
author_id INT,
FOREIGN KEY(book_id) REFERENCES book(id),
FOREIGN KEY(author_id) REFERENCES author(id) 一个书可以有多个作者,一个作者可以出版多本书
);
二、创建模型
model.py
# -*- encoding:utf-8 -*- from django.db import models # Create your models here.
''' Book Publish Author AuthorDetail Book2Author 会自定生成 Book -- Publish 一对多 Author -- AuthorDetail 一对一 Book -- Author 多对多 Book2Author '''
# 作者详情表 class AuthorDetail(models.Model): # id字段是自动添加的,如果不加主键数据库迁移的时候它也会给你默认生成一个id的字段,可以不写nid,写了就用你写的。 nid = models.AutoField(primary_key=True) birthday = models.DateField() telephone = models.BigIntegerField() addr = models.CharField(max_length=64) # 作者表 class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() # 与AuthorDetail建立一对一的关系 # to_field="nid"这个可加可不加,它会默认去关联主键 # on_delete=models.CASCADE这句不写会报错 authorDetail = models.OneToOneField(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE) def __str__(self): return self.name # 出版社表 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建立一对多的关系,外键字段建立在多的一方;django会自动给你补全publish_id; to就是foreign key哪个;加上引号就会在全局里边找; publish = models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE,null=True) # 关联主键nid;这句话相当于下面两句;在django2.0要加上on_delete=models.CASCADE;null=True是允许这个字段为空 ''' publish_id INT, FOREIGN KEY(publish_id)REFERENCES publish(id) to_field这个字段的nid主键;上边的publish在数据库迁移的时候就是这两句话 ''' # 多对多,会自动生成第三张表;下面的几个意思是一样的 authors = models.ManyToManyField(to="Author") def __str__(self): return self.title ''' CREATE TABLE book2author( 上边那一句话执行的结果就相当于会生成这个;book_authors它就是这样拼的 id INT PRIMARY KEY auto_increment, book_id INT, author_id INT, FOREIGN KEY(book_id)REFERENCES book(id), FOREIGN KEY(author_id)REFERENCES author(id), ) ''' # class Book2Author(models.Model): 这是自己写的第三张表 # nid = models.AutoField(primary_key=True) # book = models.ForeignKey(to="Book") to_field="nid" # author = models.ForeignKey(to="Author")
''' 数据库迁移 python manage.py makemigrations python manage.py migrate '''
注意事项:
- 表的名称
myapp_modelName
,是根据 模型中的元数据自动生成的,也可以覆写为别的名称 id
字段是自动添加的- 对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名 如 authordetail_id 、 publish_id 、book_id 、author_id
- 这个例子中的
CREATE TABLE
SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句。 - 定义好模型之后,你需要告诉Django _使用_这些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加
models.py
所在应用的名称。 - 外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。
一对一就是oneToOneField;一对多就是ForeignKey;它俩是一样的,会在那张表里边多生成一个字段,加一个_id+一个约束关系;多对多就是ManyToManyField,会生成一个第三张关系表;
三、多表 - 添加
# -*- encoding:utf-8 -*- from django.shortcuts import render,HttpResponse # Create your views here. from app01.models import * def add(request): ''' 绑定关系视图 :param request: :return: ''' # pub = Publish.objects.create(name="人民出版社",email="123@qq.com",city="北京") ################################### 一对多添加记录 ################################### # 方式1: # 为book表绑定出版社:book ----- publish # book_obj = Book.objects.create(title="红楼梦",price=80,publishDate="2008-7-7",publish_id=1) # print(book_obj) # Book object (3) # print(book_obj.title) # 红楼梦 # print(book_obj.price) # 80 # 方式2: # pub_obj= Publish.objects.filter(nid=1).first() # # book_obj = Book.objects.create(title="西游记", price=80, publishDate="2008-7-7", publish=pub_obj) # print(book_obj.title) # 西游记 # print(book_obj.price) # 80 # print(book_obj.publishDate) # 2008-7-7 # print(book_obj.publish) # Publish object (1) # 与这本书籍关联的出版社对象 # print(book_obj.publish_id) # 1 ################################### 一对多查询记录 ################################### # 查询西游记的出版社对应的邮箱 # 太繁琐!!! # obj_id = Book.objects.filter(title="西游记").first().publish_id # pub_obj = Publish.objects.filter(nid=obj_id).first() # print(pub_obj.email) # 通过这本书的对象可以直接得到出版社的对象:book_obj.publish # book_obj = Book.objects.filter(title="西游记").first() # print(book_obj.publish.email) ################################### 多对多添加记录 ################################### # book_obj = Book.objects.create(title="水浒传", price=80, publishDate="2008-7-7", publish_id=1) # # mm = Author.objects.get(name='mm') # tt = Author.objects.get(name='tt') # 由于app01_book_authors表不是我们代码生成的,是在创建多对多的关系的时候创建的,所以不能直接使用这个表来写书籍和 # 作者的关系,需要使用一个接口 # 绑定多对多的API # book_obj.authors.add(mm,tt) # # 其他写法 # book_obj.authors.add(1,2) # book_obj.authors.add(*[1,2]) # 可以单独绑定一个author # book_obj = Book.objects.filter(nid=6).first() # book_obj.authors.add(2) # 解除多对多的关系 # book_obj = Book.objects.filter(nid=6).first() # book_obj.authors.remove(2) # 2表示的是nid=2的author # book_obj.authors.remove(1,2) # book_obj.authors.remove(*[1,2]) # book_obj.authors.clear() # 清空 # print(book_obj.authors.all()) # [obj1,obj2...] queryset:与这本书关联的所有作者对象的集合 # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]> # 查询主键为6的书籍的所有作者的名字 # ret = book_obj.authors.all().values("name") # print(ret) # <QuerySet [{'name': 'mm'}, {'name': 'tt'}]> return HttpResponse("OK")
四、查询 - 基于对象 - 跨表
''' A-B 正向查询:关联属性在A表中,A查B 反向查询:关联属性在A表中,B查A 1.基于对象的跨表查询(子查询) # 一对多查询 正向查询按字段 反向查询按表名小写_set.all() book_obj.publish Book(关联属性:publish)对象 -------------------> Publish对象 Book(关联属性:publish)对象 <------------------- Publish对象 publish_obj.book_set.all() # queryset() # 多对多查询 正向查询按字段 反向查询按表名小写_set.all() book_obj.authors.all() Book(关联属性:authors)对象 -------------------> Author对象 Book(关联属性:authors)对象 <------------------- Author对象 aurhors_obj.book_set.all() # queryset() # 一对一查询 正向查询按字段 反向查询按表名小写 author_obj.authorDetail Author(关联属性:authorDetail)对象 -------------------> AuthorDetail对象 Author(关联属性:authorDetail)对象 <------------------- AuthorDetail对象 authorDetail_obj.author ''' def query(request): ''' 跨表查询: 1.基于对象查询 2.基于双下划线查询 3.聚合与分组查询 4.F 与 Q查询 :param request: :return: ''' #--------------------------------------- 1.基于对象的跨表查询(子查询) --------------------------------------- # 一对多正向查询 # 查询水浒传这本书的出版社的名字 # book_obj = Book.objects.filter(title="水浒传").first() # print(book_obj.publish.name) # 与这本书关联的出版社对象 # 人民出版社 # 一对多反向查询 # 查询人民出版社出版过的书籍名称 # publish_obj = Publish.objects.filter(name="人民出版社").first() # print(publish_obj.book_set.all()) # 多对多正向查询 # 查询水浒传这本书的所有作者的名字 # book_obj = Book.objects.filter(title="水浒传").first() # print(book_obj.authors.all()) # queryset对象 # <QuerySet [<Author: mm>, <Author: tt>]> # author_list = book_obj.authors.all() # for author in author_list: # print(author.name) # mm # tt # 多对多反向查询 # 查询作者mm写的所有书的名字 # author_obj = Author.objects.filter(name="mm").first() # book_list = author_obj.book_set.all() # for book in book_list: # print(book.title) # 水浒传 # 一对一正向查询 # 查询mm的手机号 # author_obj = Author.objects.filter(name="mm").first() # print(author_obj.authorDetail.telephone) # 110 # 一对一反向查询 # 查询手机号为911的作者姓名和年龄 # authorDetail = AuthorDetail.objects.filter(telephone="911").first() # print(authorDetail.author.name,authorDetail.author.age) # tt 20
五、查询 - 基于双下划线(join)- 跨表
Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的 model 为止。
关键点:正向查询按字段,反向查询按表名。
''' A-B 正向查询:关联属性在A表中,A查B 反向查询:关联属性在A表中,B查A 2.基于双下划线的跨表查询(join查询) 正向查询按字段 反向查询按表名小写 ''' def query(request): # --------------------------------------- 2.基于双下划线的跨表查询(join查询) --------------------------------------- ''' 正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表 ''' # 一对多查询 # 查询水浒传这本书的出版社的名字 # 方式一:正向查询 # ret = Book.objects.filter(title="水浒传").values("publish__name") # values相当于sql中的select # print(ret) # <QuerySet [{'publish__name': '人民出版社'}]> # 方式二:反向查询 # ret = Publish.objects.filter(book__title="水浒传").values("name") # print(ret) # <QuerySet [{'name': '人民出版社'}]> ''' sql写法: SELECT app01_publish.name FROM app01_book INNER JOIN app01_publish ON app01_book.publish_id = app01_publish.nid WHERE app01_book.title="水浒传" ''' # 多对多查询 # 查询水浒传这本书的所有作者的名字 # 方式一:正向查询,按字段authors通知ORM引擎join book_authors与author表 # 需求:通过Book表join与其关联的Author表, # ret = Book.objects.filter(title="水浒传").values("authors__name") # print(ret) # <QuerySet [{'authors__name': 'mm'}, {'authors__name': 'tt'}]> # 方式二:反向查询,按表名小写book通知ORM引擎join book_authors与book表 # 需求:通过Author表join与其关联的Book表, # ret = Author.objects.filter(book__title="水浒传").values("name") # print(ret) # <QuerySet [{'authors__name': 'mm'}, {'authors__name': 'tt'}]> ''' sql写法: SELECT app01_author.name FROM app01_book INNER JOIN app01_book_authors ON app01_book.nid = app01_book_authors.book_id INNER JOIN app01_author ON app01_book_authors.author_id = app01_author.nid WHERE app01_book.title="水浒传" ''' # 一对一查询 # 查询mm的手机号 # 方式一:正向查询 # ret = Author.objects.filter(name="mm").values("authorDetail__telephone") # print(ret) # <QuerySet [{'authorDetail__telephone': 110}]> # 方式二:反向查询 # ret = AuthorDetail.objects.filter(author__name="mm").values("telephone") # print(ret) # <QuerySet [{'telephone': 110}]> # 进阶练习: # 练习:手机号以110开头的作者出版过的所有书籍名称以及书籍出版社名称 # book表为基表: # 方式一: # 需求:通过Book表join AuthorDetail表,Book与AuthorDetail无关联,所以必须连续跨表 # ret = Book.objects.filter(authors__authorDetail__telephone__startswith="110").values("title","publish__name") # print(ret) # <QuerySet [{'publish__name': '人民出版社', 'title': '水浒传'}]> # 方式二: # 需求:通过AuthorDetail表 # ret = AuthorDetail.objects.filter(telephone__startswith="110").values("author__book__title","author__book__publish__name") # print(ret) # <QuerySet [{'author__book__title': '水浒传', 'author__book__publish__name': '人民出版社'}]> # 方式三: # 需求:通过Author表 # ret = Author.objects.filter(authorDetail__telephone__startswith="110").values("book__title","book__publish__name") # print(ret) # <QuerySet [{'book__publish__name': '人民出版社', 'book__title': '水浒传'}]>
六、聚合查询 - 分组查询
models.py(增加一个emp表)
class Emp(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() salary=models.DecimalField(max_digits=8,decimal_places=2) dep=models.CharField(max_length=32) province=models.CharField(max_length=32)
def query(request): # --------------------------------------- 3.聚合与分组查询 --------------------------------------- # --------------------------------------->聚合 aggregate:聚合统计函数,返回值是一个字典,不再是queryset # 查询所有书籍的平均价格 from django.db.models import Avg,Max,Min,Count # ret = Book.objects.all().aggregate(Avg("price")) # print(ret) # {'price__avg': 80.0} # --------------------------------------->分组查询 annotate:返回值依然是queryset # ---------------------->单表分组查询: # 示例1: # 查询每一个部门的名称以及员工的平均薪水 # sql:SELECT dep,Avg(salary) FROM app01_emp GROUP BY dep # ret = Emp.objects.values("dep").annotate(avg_salary=Avg("salary")) # print(ret) # <QuerySet [{'dep': '教学部', 'avg_salary': 51000.0}, {'dep': '保安部', 'avg_salary': 5000.0}]> # 单表分组查询的ORM语法:单表模型.objects.values("group by的字段").annotate(聚合函数("统计字段")) # 示例2: # 查询每一个省份的名称以及对应的员工数 # sql:SELECT province,Count(id) FROM app01_emp GROUP BY province # ret = Emp.objects.values("province").annotate(c=Count("id")) # print(ret) # <QuerySet [{'c': 2, 'province': '山东省'}, {'c': 1, 'province': '河北省'}]> # 补充知识点: # ret = Emp.objects.all() # print(ret) # sql:select * from emp # ret = Emp.objects.all().values("name") # print(ret) # sql:select name from emp # 在单表分组下,按着主键进行group by是没有任何意义的 # ---------------------->跨表分组查询: # 示例1:查询每一个出版社的名称以及出版的书籍个数 # 分组查询sql: # SELECT app01_publish.name, Count("title") FROM app01_book # INNER JOIN app01_publish # ON app01_book.publish_id = app01_publish.nid # GROUP BY app01_publish.nid; # 思考:如何用ORM语法实现跨表分组查询 # ret = Publish.objects.values("nid").annotate(c=Count("book__title")) # print(ret) # <QuerySet [{'c': 3, 'nid': 1}, {'c': 1, 'nid': 2}]> # ret = Publish.objects.values("name").annotate(c=Count("book__title")) # print(ret) # <QuerySet [{'c': 3, 'name': '人民出版社'}, {'c': 1, 'name': '南京出版社'}]> # ret = Publish.objects.values("nid").annotate(c=Count("book__title")).values("name","c") # print(ret) # <QuerySet [{'name': '人民出版社', 'c': 3}, {'name': '南京出版社', 'c': 1}]> # 示例2:查询每一个作者的名字以及出版过的书籍的的最高价格 # sql: # SELECT app01_author.name, MAX(app01_book.price) FROM app01_author # INNER JOIN app01_book_authors # ON app01_author.nid = app01_book_authors.author_id # INNER JOIN app01_book # ON app01_book_authors.book_id = app01_book.nid # GROUP BY app01_author.nid; # ret = Author.objects.values("nid").annotate(m=Max("book__price")).values("name","m") # print(ret) # <QuerySet [{'name': 'mm', 'm': Decimal('80.00')}, {'name': 'tt', 'm': Decimal('80.00')}]> # 总结跨表的分组查询的模型; # 每一个后的表模型.objects.values("pk").annotate(聚合函数(关联表__统计字段)) # 示例3:查询每一个书籍的名称以及对应的作者个数 # ret = Book.objects.values("pk").annotate(c=Count("authors__nid")).values('title',"c") # print(ret) # <QuerySet [{'title': '红楼梦', 'c': 0}, {'title': '西游记', 'c': 0}, {'title': '三国演义', 'c': 0}, {'title': '水浒传', 'c': 2}]> ############################ 跨表分组查询的另一种玩法 ############################ # 示例1:查询每一个出版社的名称以及出版的书籍个数 # ret = Publish.objects.all().annotate(c=Count("book__title")).values("name","c") # print(ret) # <QuerySet [{'name': '人民出版社', 'c': 3}, {'name': '南京出版社', 'c': 1}]> # 练习: # 统计每一本以py开头的书籍的作者个数: # ret = Book.objects.filter(title__startswith="py").values("pk").annotate(c=Count("authors__name")).values("title","c") # 统计不止一个作者的书籍: # ret = Book.objects.values("pk").annotate(c=Count("authors__name")).filter(c__gt=1).values("title","c") # print(ret) # <QuerySet [{'c': 2, 'title': '水浒传'}]>
七、F查询 - Q查询
models.py(Book表添加read_num和comment_num字段)
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) read_num = models.IntegerField() comment_num = models.IntegerField() publish = models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE,null=True) authors = models.ManyToManyField(to="Author")
给一个已经存在的有数据的表添加新的 字段带来的问题:
解决方法:添加default=0
def query(request): ############################ F查询和Q查询 ############################ from django.db.models import F,Q # 示例1:查询评论数大于阅读数的书籍 # ret = Book.objects.filter(comment_num__gt=F("read_num")) # print(ret) # <QuerySet [<Book: 西游记>, <Book: 水浒传>]> # 示例2:所有书籍价格提高10元 # Book.objects.all().update(price=F("price")+10) # 示例3:查询书籍名称为红楼梦,价格为90的书籍 # ret = Book.objects.filter(title="红楼梦",price=90) # 只可以表示且 # Q的字段不仅可以表示且,也可以表示或 # ret = Book.objects.filter(Q(title="红楼梦")|Q(price=90)) # print(ret) # <QuerySet [<Book: 红楼梦>, <Book: 西游记>, <Book: 三国演义>, <Book: 水浒传>]> # 示例4:过滤书名不等于红楼梦的书籍 ret = Book.objects.filter(~Q(title="红楼梦")) print(ret) # <QuerySet [<Book: 西游记>, <Book: 三国演义>, <Book: 水浒传>]> return HttpResponse("OK")
八、关联管理器
http://www.cnblogs.com/liwenzhou/p/8660826.html
http://www.cnblogs.com /yuanchenqi/articles/8978167.html
https://docs.djangoproject.com/en/1.11/ref/models/querysets/
九、补充知识
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1. 内容回顾 1. 常用字段和字段参数 1. 常用字段 1. AutoField primary_key=True # 设置为主键 2. CharField max_length=32 # 设置最大长度 3. IntegerField 4. BigInterField 5. TextField 6. DateField auto_now_add # 创建这条数据时自动添加当前时间 auto_now # 每次更新的时候都自动更新时间 7. DateTimeField 同上 ... 常用参数: default="" # 设置默认值 null=True # 可以为空 unique=True # 该字段在数据库中不能重复 2. 关系字段 1. 外键 ForeignKey 1. 外键通常放在多(一对多的多)的那一边 2. 参数 1. to=“表名” 2. related_name="xx" 用来替换反向查询时的 表名_set 3. on_delete=models.CASCADE 2. 一对一 OneToOneField 1. 什么时候用 作者和作者详情 3. 多对多 ManyToManyField 1. 三种方式 1. 不用ManyToMany 2. 自带的ManyToMany, 自动帮我创建第三张表 3. 自定义第三张表 # 相亲网站 # 男孩 class Boy(models.Model): name = models.CharField(max_length=32) girls = models.ManyToManyField(to='Girl', through="Info", through_fields=("boy1", "girl1")) # 能满足多对多的关系,但是少点东西 # 女孩 class Girl(models.Model): name = models.CharField(max_length=32) # through_fields=('field1', 'field2'), # 你把多对多建在那个表,field1就是这个表的名字 # field2是你目标表的表名 # boys = models.ManyToManyField(to=Boy, through="Info", through_fields=("girl1", "boy1")) # 能满足多对多的关系,但是少点东西 # 约会记录 # 男孩1 女孩1 # 男孩2 女孩1 # 男孩1 女孩2 # 自己创建第三张表, 记录约会的记录 class Info(models.Model): girl1 = models.ForeignKey(to=Girl) boy1 = models.ForeignKey(to=Boy) # 其他补充字段 date = models.DateTimeField(auto_now_add=True) 3. 元信息 # 定义元信息 class Meta: ordering = ("price", ) # 默认按照价格排序 db_table = "book" # 指定在数据库中创建表的表名 unique_together = ("title", "price") # 多字段联合唯一 2. ORM操作 1. 单表13个 --> 永远不要怀疑自己!要自信!!! 混乱即阶梯! 返回QuerySet的有: 1. all() 3. filter() 4. exclude() 7. values_list() --> 元祖 8. values() --> 字典 9. order_by() 10. reverse() 13. distinct() 返回对象: 2. get() 5. first() 6. last() 返回数字: 11. count() 返回布尔值: 12. exist() 双下划线: id__lt=10 ... 跨表的双下划线: models.Book.objects.filter(author__name=“小仙女") models.Book.objects.filter(author__detail__age=18) ... 2. 关系表的操作 1. 外键 1. 正向查找 --> 具体的对象 直接找 2. 反向查找 --> 对象的列表 .表名(小写)_set.all() 2. 多对多 1. 正向查找 直接找 --> 对象的列表 2. 反向查找 表名_set.all() --> 对象的列表 多对多才有的: .create() --> author_obj.books.create(title="番茄物语") .add(1,2,3) .clear() -->清空 .remove(1) .set([1,2,3]/QuerySet对象) 3.聚合和分组 1. aggregate() 2. annotate() ---> GROUP BY 4. F和Q 1. 同一张表的不同列作比较 2. 多个条件做查询 5. 事务 try: from django.db import transaction with transaction.atomic(): new_publisher = models.Publisher.objects.create(name="新华出版社CCC") # 再去创建新书 # new_book = models.Book.objects.create(title="新华字典", price=3.5, publisher_id=new_publisher.id) new_book = models.Book.objects.create(titl="新华字典CCC", price=3.5, publisher=new_publisher) except Exception as e: print(str(e)) 6. 如何在Python脚本加载Django环境 import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "项目名.settings") import django django.setup() # 引用Django内部的变量
事务
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() import datetime from app01 import models try: from django.db import transaction with transaction.atomic(): new_publisher = models.Publisher.objects.create(name="火星出版社") models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10) # 指定一个不存在的出版社id except Exception as e: print(str(e))
在Python脚本中调用Django环境
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() from app01 import models books = models.Book.objects.all() print(books)
orm参数