62 Django

[TOC]

基于双下划线的连表查询

1from django.db import models 2 3# Create your models here. 4 5class Author(models.Model): 6 """ 7 作者表 8 """ 9 name=models.CharField( max_length=32) 10 age=models.IntegerField() 11 # authorDetail=models.OneToOneField(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE) # 12 auth=models.OneToOneField("AuthorDetail",on_delete=models.CASCADE) 13 14class AuthorDetail(models.Model): 15 """ 16 作者详细信息表 17 """ 18 birthday=models.DateField() 19 telephone=models.CharField(max_length=11) 20 addr=models.CharField(max_length=64) 21 # class Meta: 22 # db_table='authordetail' #指定表名 23 # ordering = ['-id',] 24class Publish(models.Model): 25 """ 26 出版社表 27 """ 28 name=models.CharField( max_length=32) 29 city=models.CharField( max_length=32) 30 31class Book(models.Model): 32 """ 33 书籍表 34 """ 35 title = models.CharField( max_length=32) 36 publishDate=models.DateField() 37 price=models.DecimalField(max_digits=5,decimal_places=2) 38 pub=models.ForeignKey(to="Publish",on_delete=models.CASCADE,) 39 authors=models.ManyToManyField('Author',)

一对一:

1# 查询alex的电话号码 2 3正向:依靠属性 4ret = models.Author.objects.filter(name='alex').values('auth__telephone') 5# <QuerySet [{'auth__telephone': '110'}]> 6 7反向:依靠类名(表名)小写 8ret = models.AuthorDetail.objects.filter(author__name='alex').values('telephone') 9# <QuerySet [{'telephone': '110'}]> 10 11print(ret)

多对一:

1# 查询一下 xxx 这本书的出版社 2 3# 正向:依靠属性 4ret=models.Book.objects.filter(title='xxx').values('pub__name') 5# <QuerySet [{'pub__name': '人民出版社'}]> 6 7# 反向:依靠类名(表名)小写 8ret=models.Publish.objects.filter(book__title='xxx').values('name') 9# <QuerySet [{'name': '人民出版社'}]> 10 11 12# 查询 24期出版社 出版了那些书 13# 反向 14ret=models.Publish.objects.filter(name='24期出版社').values('book__title') 15 16# <QuerySet [{'book__title': 'alex与meet的爱恨'}, {'book__title': '那年的24期'}]> 17 18# 正向 19ret=models.Book.objects.filter(pub__name='24期出版社').values('title') 20 21# <QuerySet [{'title': 'alex与meet的爱恨'}, {'title': '那年的24期'}]>

多对多:

1# xxx 这本书 是有哪些作者写的 2 3# 正向查询:属性 4ret=models.Book.objects.filter(title='xxx').values('authors__name') 5# <QuerySet [{'authors__name': 'alex'}, {'authors__name': 'meet'}, {'authors__name': 'liu'}]> 6 7""" 8原生sql语句: 9select app01_author.name from app01_book INNER JOIN app01_book_authors on app01_book.id = app01_book_authors.book_id 10 INNER JOIN app01_author on app01_book_authors.author_id = app01_author.id 11 where app01_book.title='xxx; 12""" 13 14# 反向查询:类名(表名) 15ret=models.Author.objects.filter(book__title='xxx').values('name') 16 17# <QuerySet [{'name': 'alex'}, {'name': 'meet'}, {'name': 'liu'}]>

related_name

反向查询,替代 表名小写 或者 表名_set 。必须替代,否则会报错。

1pub = ForeignKey(Publish, related_name='bookList') 2 3ret=models.Book.objects.filter(title='xxx').values('bookList__name')

聚合查询 aggregate

1# 统计书的平均价格以及最高价格 2 3from django.db.models import Avg, Max 4ret = models.Book.objects.all().aggregate(Avg('price'),Max('price')) # 结果是python字典, 也就是说聚合查询是orm的结束语句,一般放在最后. 5# {'price__avg': 137.833333, 'price__max': Decimal('222.00')} 6 7ret = models.Book.objects.all().aggregate(a=Avg('price'),m=Max('price')) 8# 给键取名字 9{'a': 137.833333, 'm': Decimal('222.00')}

分组查询 annotate

必须起别名。

1# 每个出版社的书的平均价格 2 3models.Book.objects.values('pub__id').annotate(a=Avg('price')) 4 5# 按属性pub分组(按publish表的id分组) 6# <QuerySet [{'pub__id': 1, 'a': 186.0}, {'pub__id': 2, 'a': 100.0}, {'pub__id': 3, 'a': 5.0}, {'pub__id': 4, 'a': 175.0}]> 7 8 9models.Book.objects.values('pub_id').annotate(a=Avg('price')) 10 11# 按book表的pub_id字段分组 12# <QuerySet [{'pub_id': 1, 'a': 186.0}, {'pub_id': 2, 'a': 100.0}, {'pub_id': 3, 'a': 5.0}, {'pub_id': 4, 'a': 175.0}]> 13 14 15models.Publish.objects.annotate(a=Aug('book__price')).values('a') 16# 连表后拿Publish的id进行分组,a是别名 17<QuerySet [{'a': 186.0}, {'a': 100.0}, {'a': 5.0}, {'a': 175.0}]> 18

F查询--锁定本表字段

本表字段中,要对两个字段的值做比较,F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

1from django.db.models import F 2 3ret = models.Book.objects.filter(字段1__gt=F('字段2')) 4# 查询book表中 字段1 大于 字段2的记录 5 6django支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。

修改操作也可以使用F函数。

1# 将所有书籍价格提高10 2 3models.Book.objects.all().update( 4 price=F('price')+10 5) 6

Q查询 -- 或 | 、与 & 、非 ~

注意:, 是 AND查询

1from django.db.models import Q 2 3# 查询书籍价格大于200或者价格小于100 4models.Book.objects.filter(Q(price__gt=200)|Q(price__lt=100)) 5

可以多层嵌套

1Q(Q(price__gt=200)|Q(price__lt=100))|Q(...) 2

与关键字参数一起使用,Q 对象必须位于所有关键字参数的前面。

1查询书籍价格大于200或者价格小于100并且id=2 2models.Book.objects.filter(Q(price__gt=200)|Q(price__lt=100),id=2) 3

作业:

1 查询每个作者的姓名以及出版的书的最高价格

1ret=models.Author.objects.annotate(max=Max('book__price')).values('name', 'max') 2 3print(ret) 4

2 查询作者id大于2作者的姓名以及出版的书的最高价格

1ret = models.Author.objects.filter(id__gt=2).annotate(max=Max('book__price')).values('name', 'max') 2

3 查询作者id大于2或者作者年龄大于等于20岁的作者的姓名以及出版的书的最高价格

1ret = models.Author.objects.filter(Q(id__gt=2)|Q(age__gte=20)).annotate(max=Max('book__price')).values('name', 'max') 2

4 查询每个作者出版的书的最高价格 的平均值

1ret = models.Author.objects.annotate(max=Max('book__price')).aggregate(Avg('max')) 2

5 每个作者出版的所有书的最高价格以及最高价格的那本书的名称

1select title,price from (select app01_author.id,app01_book.title,app01_book.price from app01_author INNER JOIN app01_book_authors on app01_author.id= 2 app01_book_authors.author_id INNER JOIN app01_book on app01_book.id= 3 app01_book_authors.book_id ORDER BY app01_book.price desc) as b GROUP BY id; 4

ORM执行原生sql语句

在模型查询API(接口)不够用的情况下,我们还可以使用原始的SQL语句进行查询。

Django 提供两种方法使用原始SQL进行查询:一种是使用raw()方法,进行原始SQL查询并返回模型实例;另一种是完全避开模型层,直接执行自定义的SQL语句。

执行原生查询

raw()管理器方法用于原始的SQL查询,并返回模型的实例:

raw()语法查询必须包含主键。

返回一个RawQuerySet对象

models.Book.objects.raw('select price from app01_book where id=2')

直接执行自定义SQL

1from django.db import connection, connections 2cursor = connection.cursor() # cursor = connections['default'].cursor() 3cursor.execute('SELECT * from auth_user where id = %s', [1]) 4ret = cursor.fetchone()

Python脚本中调用Django环境(django外部脚本使用models)

如果你想通过自己创建的python文件在django项目中使用django的models,那么就需要调用django的环境:

复制代码

1import os 2 3if __name__ == '__main__': 4 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") 5 import django 6 django.setup() 7 8 from app01 import models #引入也要写在上面三句之后 9 10 books = models.Book.objects.all() 11 print(books)

事务与锁

Django orm中的锁

1models.Book.objects.select_for_update().filter(id=1) # 给id=1的行级加锁 2

事务开启

1. 全局开启

整个视图函数中,统一个http请求对应的所有sql都放在一个事务中执行(要么所有都成功,要么所有都失败)。

1DATABASES = { 2 'default': { 3 'ENGINE': 'django.db.backends.mysql', 4 'NAME': 'orm', 5 'HOST': '127.0.0.1', 6 'PORT': '3306', 7 'USER': 'root', 8 'PASSWORD': '123', 9 "ATOMIC_REQUESTS": True, #全局开启事务,绑定的是http请求响应整个过程 10 } 11

2. 局部开启

atomic(using=None, savepoint=True)[source]

原子性是数据库事务的一个属性。使用atomic,我们就可以创建一个具备原子性的代码块。一旦代码块正常运行完毕,所有的修改会被提交到数据库。反之,如果有异常,更改会被回滚。

被atomic管理起来的代码块还可以内嵌到方法中。这样的话,即便内部代码块正常运行,如果外部代码块抛出异常的话,它也没有办法把它的修改提交到数据库中。

1方式1:给函数做装饰器来使用 2from django.db import transaction 3 4@transaction.atomic 5def viewfunc(request): 6 # This code executes inside a transaction. 7 do_stuff() 8 9 10方式2: 作为上下文管理器来使用,其实就是设置事务的保存点 11(给某一视图函数中部分sql语句加锁) 12 13def viewfunc(request): 14 15 do_stuff() 16 with transaction.atomic(): # 设置保存点 17 pass
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )