Django学习——图书相关表关系建立、基于双下划线的跨表查询、聚合查询、分组查询、F查询、Q查询、admin的使用、使用脚本调用Django、Django查看源生sql
阅读原文时间:2022年05月05日阅读:1

0 图书相关表关系建立

1.5个表
2.书籍表,作者表,作者详情表(垂直分表),出版社表,书籍和作者表(多对多关系)
一对一 多对多 本质都是一对多  外键关系
3.一对一的关系,关联字段可以写在任意一方
4.一对多的关系,关联字段写在多的一方
5.多对多的关系,必须建立第三张表(orm中,可以用一个字段表示,这个字段可以写在任意一方)

6 把表关系同步到数据库中
    -python manage.py makemigrations  # 在migrations文件夹下记录一下
    -python manage.py migrate       # 把记录变更到数据库

7 表关系
class Book(models.Model):
    nid = models.AutoField(primary_key=True)  # 自增,主键
    name = models.CharField(max_length=32)  # varchar 32
    price = models.DecimalField(max_digits=5, decimal_places=2)  # 长度 5 小数点后2位
    publish_date = models.DateField()  # 年月日类型
    # 阅读数
    # reat_num=models.IntegerField(default=0)
    # 评论数
    # commit_num=models.IntegerField(default=0)

    # to='Publish'也可以写成 to=Publish 但该类Publish要位于上方。建议加引号写
    # 2.x以后必须加on_delete,否则报错
    # models.CASCADE:级联删除,设为默认值,设为空,设为指定的值,不做处理
    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
    # publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.SET_DEFAULT,default=0)
    # publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.SET_NULL)
    # publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.DO_NOTHING)
    # 在数据库中,根本没有这个字段,orm用来查询,映射成一个表
    # 如果我不这么写,需要手动建立第三张表,中介模型
    authors=models.ManyToManyField(to='Author')
    def __str__(self):
        return self.name

class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)
    # author_detail = models.ForeignKey(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)

class AuthorDatail(models.Model):
    nid = models.AutoField(primary_key=True)
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    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()  # 本质是varchar类型

1 基于双下划线的跨表查询

1 基于对象的跨表查
    -子查询,多次查询
2 基于双下划线的跨表查
    -多表连接查询

 from app01 import models
# 正反向:正向,关联字段在当前对象中,去另一个表中查

    # 查询主键为1的书籍的出版社所在的城市
    # book = models.Book.objects.filter(pk=1).first()
    # print(book.publish.city)

    # res = models.Publish.objects.filter(book__nid=1).values('city')
    # res = models.Book.objects.filter(pk=1).values('publish__city')
    # print(res)

    # 查询所有住址在北京的作者的姓名
    # res = models.Author.objects.filter(author_detail__addr='北京').values('name')
    # res = models.AuthorDatail.objects.filter(addr='北京').values('author__name')
    # print(res)

    # 查询egon出过的所有书籍的名字
    # res = models.Book.objects.filter(authors__name='egon').values('name')
    # res = models.Author.objects.filter(name='egon').values('book__name')
    # print(res)

    # 查询北京出版社出版过的所有书籍的名字以及作者的姓名和地址
    # res = models.Book.objects.filter(publish__name='北京出版社').values('name','authors__name','authors__author_detail__addr')
    # res = models.Publish.objects.filter(name='北京出版社').values('name','book__name','book__authors__name','book__authors__author_detail__addr')
    # res = models.Author.objects.filter(book__publish__name='北京出版社').values('book__publish__name','book__name','name','author_detail__addr')
    # res = models.AuthorDatail.objects.filter(author__book__publish__name='北京出版社').values('author__book__publish__name','author__book__name','author__name','addr')
    # print(res)

2 聚合查询

1 聚合函数,sum,max,min,count,avg
# 聚合查询
# 计算所有图书的平均价格
from django.db.models import Sum,Avg,Max,Min,Count
res = models.Book.objects.all().aggregate(Avg('price'))
print(res)
# 计算所有图书的最高价格
res = models.Book.objects.all().aggregate(Max('price'))
print(res)
# 计算所有图书的总价格
res = models.Book.objects.all().aggregate(Sum('price'))
print(res)

2 把聚合结果字段重命名
# 查询结果重命名
res = models.Book.objects.filter(authors__name='egon').aggregate(总价格=Sum('price'))
print(res)

# 计算egon出版图书的总价格 平均价格
res = models.Book.objects.filter(authors__name='egon').aggregate(book_sum=Sum('price'),book_avg=Avg('price'))
print(res)

3 分组查询

annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。

总结 :跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询。 

4 F查询

# F 查询,取出某个字段对应的值
from django.db.models import F,Q
# 查询评论数大于阅读数的书籍
# res = models.Book.objects.filter(commit_num__gt=F('read_num'))
# print(res)

# 把所有图书价格+1
res = models.Book.objects.all().update(price=F('price')+1)
print(res)  # 影响的行数

5 Q查询

# Q查询:构造出与 & 或 | 非 ~
from django.db.models import Q
# 查询名字叫红楼梦或者价格大于100的书
# res = models.Book.objects.filter(name='红楼梦',price__gt=100)  # and 并且
# res = models.Book.objects.filter(Q(name='红楼梦')|Q(price__gt=100))
# 查询名字不是红楼梦的书
# res = models.Book.objects.filter(~Q(name='红楼梦'))
# print(res)
# 查询名字不是红楼梦,并且价格大于100的书
# res = models.Book.objects.filter(~Q(name='红楼梦'),Q(price__gt=100))
# res = models.Book.objects.filter(~Q(name='红楼梦')&Q(price__gt=100))
# res = models.Book.objects.filter(~Q(name='红楼梦'),price__gt=100)
res = models.Book.objects.filter(~Q(name='红楼梦'),price__gt='100')
# print(res.query)
print(res)

补充:

1 普通函数以__开头
    说明当前函数只在当前模块(py)下使用,尽量不在外部调用

2 mysql
    -utf8: 2个字节表示一个字符
    -utf8mb4: 等同于真正意义上的utf-8 变长
    -utf-8: 1-4个字节,表示一个字符

3 Django的orm使用pymysql连接mysql
    -需要加这一句话(本质就是猴子补丁的应用)
        import pymysql
        pymysql.install_as_MySQLdb()
    -本质是想让它执行,放在哪里都可以
        -init中
        -settings.py中

Django admin的使用

1 后台管理,方便我们快速的录入数据
2 使用方法:
    第一步:在admin.py中把要使用的表注册
          from app01 import models
        admin.site.register(models.Book)
        admin.site.register(models.Author)
        admin.site.register(models.AuthorDatail)
        admin.site.register(models.Publish)
    第二步:创建个超级管理员
        python3 manage.py createsuperuser
        输入用户名,输入密码
    第三步:登录,录入数据
        http://127.0.0.1:8000/admin

使用脚本调用Django

 1 写一个脚本文件

import os
# 加载配置文件,跑Django的项目,最开始就是把配置文件加载上
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'books.settings')

if __name__ == '__main__':
    import django  # 安装了Django模块,就可以import
    django.setup()  # 使用环境变量中的配置文件,跑Django

    from app01 import models

Django查看源生sql

1 queryset对象.query
2 通过日志,如下,配置到settings.py中
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

作业

# 计算egon出版图书的总价格
res = models.Book.objects.filter(authors__name='egon').aggregate(Sum('price'))
print(res)
# 计算北京出版社出版的最高价格
res = models.Book.objects.filter(publish__name='北京出版社').aggregate(Max('price'))
print(res)

回顾

-1 前后端混合开发(前后端都写 全栈开发)
    前后端分离,前端的人专门写前端,后端的人专门写后端
    前端工程化 前端框架
0 Django的模板语法  不同的语言有自己的模板语法
    -dtl:在模板中写python代码  xx.html
    -php:http://www.aa7a.cn/user.php
    -java:https://www.pearvideo.com/category_loading.jsp
    -go:xx.html
    -jsp javascript=js 解释器 浏览器
    模板语法只负责把模板渲染成标准的带有HTML css js的页面
1 后续的课程
    -Django高级,ajax,分页,auth,中间件..
    -BBS项目
    -drf:写接口
    -vue
    -路飞:git celery redis 发短信...
    -flask
    -cmdb:自动化运维
    -爬虫
    -go
    -es
    -redis高级
    -rabbitmq,rpc
    -mongodb
    -mysql 主从,读写分离,分库分表
    -分布式锁,分布式id...

2 python后端开发,爬虫,自动化运维,自动化测试,python开发(写脚本)
    数据分析,go开发

3 多对多操作的api
    -add
    -remove
    -clear
    -set

book_obj.authors.remove()      # 将某个特定的对象从被关联对象集合中去除。   ====== book_obj.authors.remove(*[])
book_obj.authors.clear()       #清空被关联对象集合
book_obj.authors.set()         #先清空再设置 

4 什么情况下需要手动创建第三张表?
    -第三张表中有其他额外的字段