8、Django框架-- 分组查询、orm常用与非常用字段、orm字段参数、字段关系、手动创建第三张表、Meta元信息、原生sql查询、Django与ajax入门

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")

6 Meta元信息

# 在每一个模型类中都可以写
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>
posted @ 2022-03-07 17:28  简爱cx  阅读(38)  评论(0编辑  收藏  举报