1 分组查询
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
if __name__ == '__main__':
import django
django.setup()
from app01 import models
# 查询每一个出版社id,以及出书平均价格(单表)
# 原生sql
# select publish_id,avg(price) from book group by publish_id;
# orm实现
'''标准 annotate() 内写聚合函数
values在前,表示group by 的字段
values在后,表示取字段
filter在前,表示where条件
filter在后,表示having
'''
from django.db.models import Avg,Count,Max
# res = models.Book.objects.all().\
# values('publish_id').\
# annotate(price_ave=Avg('price')).values('publish_id','price_ave')
# print(res)
# 查询出版社id大于1的出版社id,以及出书平均价格
# res=models.Book.objects.values('publish_id').filter(publish_id__gt=1).annotate(price_ave=Avg('price')).values('publish_id','price_ave')
# print(res)
# 查询出版社id大于1的出版社id,以及出书平均价格大于30的
# res=models.Book.objects.values('publish_id').filter(publish_id__gt=1).annotate(price_ave=Avg('price')).filter(price_ave__gt=60).values('publish_id','price_ave')
# print(res)
#查询每一个出版社出版的名称和书籍个数(连表)
# 联表的话最好以group by的表作为基表
# res=models.Publish.objects.values('nid').annotate(book_count=Count('book__nid')).values('name','book_count')
# 简写成,如果基表是group by的表,就可以不写values
# res=models.Publish.objects.annotate(book_count=Count('book')).values('name','book_count')
# 以book为基表
# res=models.Book.objects.values('publish__nid').annotate(book_count=Count('nid')).values('publish__name','book_count')
# print(res)
#查询每个作者的名字,以及出版过书籍的最高价格(建议使用分组的表作为基表)
# 多对多如果不以分组表作为基表,可能会出数据问题
# res=models.Author.objects.annotate(price_max=Max('book__price')).values('name','price_max')
# res=models.Book.objects.values('authors__nid').annotate(price_max=Max('price')).values('authors__name','price_max')
# print(res)
#查询每一个书籍的名称,以及对应的作者个数
res=models.Book.objects.annotate(count=Count('authors')).values('name','count')
print(res)
##统计不止一个作者的图书
## 统计价格数大于10元,作者的图书
##统计价格数大于10元,作者个数大于1的图书
res=models.Book.objects.filter(price__gt=10).annotate(count=Count('authors')).filter(count__gt=1).values('name','price','count')
print(res)
2 orm常用和非常用字段(了解)
1 常用
AutoField IntegerField CharField DateField DateTimeField
2 不常用的
-BooleanField
-TextField
-FileField
3 对应关系
3 orm字段参数(了解)
1 null 是否可以为空
2 unique 是否唯一
3 db_index 是否给该字段建索引
4 default 默认值为
5 DateField和DateTimeField 两个参数
#### auto_now_add
配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
#### auto_now(对象.属性 对象.save()) queryset.update无效
配置上auto_now=True,每次更新数据记录的时候会更新该字段。
6 choices(知道)
-在model表模型定义的时候给某个字段指定choice
sex_choice=((1,'男'),(2,'女'),(0,'未知'))
sex =models.IntegerField(default=1,choices=sex_choice)
-在使用的时候,直接取出中文
对象.get_sex_display()
7 了解的
verbose_name Admin中显示的字段名称
blank Admin中是否允许用户输入为空
editable Admin中是否可以编辑
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
4 字段关系(了解)
1 一对以 一对多 多对多
2 ForeignKey
-to :对那张表
-to_field:对表中的某个字段
-related_name:反向操作时,使用的字段名,用于代替原反向查询时的’表名_set’
-related_query_name:反向查询操作时,使用的连接前缀,用于替换表名
-on_delete:
当删除关联表中的数据时,当前表与其关联的行的行为。
models.CASCADE
删除关联数据,与之关联也删除
models.DO_NOTHING
删除关联数据,什么都不做
models.PROTECT
删除关联数据,引发错误ProtectedError
models.SET_NULL
删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
models.SET_DEFAULT
删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
models.SET
删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
db_constraint 外键是否建立
-True:建立外键,默认是True
-False:不建立外键
-好处:不会出现脏数据
-坏处:插入的时候,效率低
-企业中:通常不建立,程序员控制
3 OneToOneField-跟ForeignKey
4 ManyToManyField:如何手动创建第三张表
5 手动创建第三张表
-字段参数
-db_table:指定第三张表的名字
-to:关联的表
-related_name 同ForeignKey字段。
-related_query_name 同ForeignKey字段。
-through:手动创建第三张表,指定通过哪个表
-through_fields:关联字段是什么
-多对多关系建立的三种方式
-第一种:自动创建(常用:第三张表没有其他字段)
-第二种:手动创建第三张表(比较常用:第三张表有多余字段)
-第三中:完全手动写第三张表
# 第一种:
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="书名")
# 通过ORM自带的ManyToManyField自动创建第三张表
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
books = models.ManyToManyField(to="Book", related_name="authors")
# 第二种
class Book1(models.Model):
title = models.CharField(max_length=32, verbose_name="书名")
# 自己创建第三张表,并通过ManyToManyField指定关联
class Author1(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
books = models.ManyToManyField(to="Book1", through="Author2Book", through_fields=("author", "book"))
# through_fields 元组的第一个值是ManyToManyField所在的表去中间表通过那个字段,就写在第一个位置
class Author2Book(models.Model):
author = models.ForeignKey(to="Author1")
book = models.ForeignKey(to="Book1")
## 基于对象的跨表查,还能继续使用
## 基于双下划綫连表查
## 原来的多对多操作api用不了了,需要手动操作
# 第三种
class Book1(models.Model):
title = models.CharField(max_length=32, verbose_name="书名")
class Author1(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
# 自己创建第三张表,分别通过外键关联书和作者
class Author2Book1(models.Model):
author = models.ForeignKey(to="Author1")
book = models.ForeignKey(to="Book1")
# 在每一个模型类中都可以写
class Meta: #元信息
db_table='lqz_publish' #表名
index_together=('name','city') # 多个字段联合索引
unique_together=('name','city') # 联合唯一
ordering=('nid', ) # 默认以哪个字段排序
7 原生sql
from app01 import models
# res=models.Author.objects.all()
# for author in res:
# print(author.sex)
# print(author.get_sex_display())
# 使用原生sql
# res=models.Author.objects.raw('select * from app01_author where nid>1')
# for author in res:
# print(author.name)
res = models.Author.objects.raw('select * from app01_book where nid>1')
for book in res:
print(book.price)
# 执行原生sql,跟对象类型无关了,查出什么字段,可以直接使用该字段
8 Django与ajax(入门)
1 概念
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。
即使用Javascript语言与服务器进行异步交互,传输的数据为XML
(当然,传输的数据不只是XML,现在更多使用json数据)
2 异步:请求发出去,不会卡在这,可以干其他事
3 局部刷新:js的dom操作,使页面局部刷新
4 基本上web页面都有很多ajax请求
8.1 写ajax跟后端交互
1 使用原生js写ajax请求(没有人用)
-第一:麻烦
-第二:区分浏览器,需要做浏览器兼容
2 现在主流做法(现成有人封装好了,jquery,axios..)
-以jquery为例讲
-后面会讲axios
后端
def ajax_test(request):
return render(request,'ajax_test.html')
def sum(request):
import time
time.sleep(2)
a1=int(request.GET.get('a1'))
a2=int(request.GET.get('a2'))
return HttpResponse(a1+a2)
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/static/jquery-3.3.1.js"></script>
</head>
<body>
<input type="text" id="a1"> + <input type="text" id="a2">=<input type="text" id="sum">
<button id="btn_submit">计算</button>
</body>
<script>
$('#btn_submit').click(function () {
var a1 = $('#a1').val()
var a2 = $('#a2').val()
// 发送ajax请求,计算,返回结果
$.ajax({
url: '/sum/', //ajax请求的地址
method: 'get',//请求方式
data: {'a1': a1, 'a2': a2}, //携带参数
success:function (data) { //服务端成功返回会回调,执行匿名函数
console.log(data)
$('#sum').val(data)
}
})
})
</script>
</html>