django框架-5

表查询数据准备及测试环境搭建

1.django自带一个sqlite3小型数据库
	该数据库功能非常有限 并且针对日期类型的数据兼容性很差 建议哈是用mysql
2.django切换MySQL数据
    django1.X
    	import pymysql
    pymysql.install_as_MySQLdb()
        django2.X   3.X    4.X
        pip install mysqlclient
3.定义模型类
class User(models.Model):
    uid = models.AutoField(primary_key=True, verbose_name='编号')
    name = models.CharField(max_length=32, verbose_name='姓名')
    age = models.IntegerField(verbose_name='年龄')
    join_time = models.DateField(auto_now_add=True)
"""
日期字段重要参数
 auto_now:每次操作数据并自动保存当前更新时间
     eg:创建时间:10:00  更新时间11:00   
 auto_add:只在创建数据的那一刻自动获取当前时间 之后如果不认为更改则不变
     eg:玩游戏注册时间
"""

image

4.执行数据库迁移命令(模型类>>>表)
	makemigrations
	migrate
5.模型层测试环境准备
方式1:先去mangage.py拷贝前四行代码和下方的启动脚本  把第二行import sys删了  然后再写三行代码    
import django
django.setup()
from app01 import models
整体如下:
import os


def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'day63.settings')
    import django
    django.setup()

    from app01 import models

image

方式2:pycharm提供测试环境
	python console命令行测试环境(但是终端一关就没了)

image

ORM常见查询关键字-13个必会操作

"""
1.当需要查询数据主键字段值的时候 可以使用pk忽略掉数据字段真正的名字
2.在模型类中可以定义一个__str__方法 便于后续数据对象被打印展示的是查看方便
3.Queryset中如果是列表套对象那么可以for循环和索引取值 但是索引不支持负数
4.虽然queryset支持索引但是当queryset没有数据的时候索引会报错 推荐使用first
    1.create()
        创建数据 返回值就是当前创建的数据对象
        ps:还可以利用类实例化对象然后调用save方法创建
    2.update()
    	更新数据
    3.delete()
    	删除数据
"""
1.filter()
	筛选数据 返回值是一个QuerySet(可以看成是列表套数据对象)
   	1.括号内不写查询条件 默认就是查询所有
	2.括号内可以填写条件 并且支持多个 逗号隔开 默认是and关系
2.all()
	查询所有数据 返回值是一个QuerySet(可以看成是列表套数据对象)
3.first()
	获取Queryset中第一个数据对象 如果为空则返回No
    ne
4.last()
	获取Queryset中最后一个数据对象 如果为空则返回None
5.get()
	直接根据条件查询具体的数据对象 但是条件不存在直接报错 不推荐使用
6.values()
	指定查询字段 结果是Queryset(可以看成是列表套字典数据)
7.values_list()
	指定查询字段 结果是Queryset(可以看成是列表套元组数据)
8.order_by()
	指定字段排序 默认是升序 在字段前加负号则为降序 并且支持多个字段排序
9.count()
	统计orm查询之后结果集中的数据格式
10.distinct()
	针对重复的数据集进行去重 一定要注意数据对象中的主键
11.exclude()
	针对括号内的条件取反进行数据查询 QuerySet(可以看成是列表套数据对象)
12.reverse()
	针对已经排了序的结果集做颠倒
13.exists()
	判断查询结果集是否有数据 返回布尔值 但是几乎不用因为所有数据自带布尔值
    
额外了解:
    raw()执行SQL语句还可以借助于模块
    from django.db import connection  
    cursor = connection.cursor()  
    cursor.execute("insert into hello_author(name) VALUES ('郭敬明')") 
    cursor.execute("update hello_author set name='韩寒' WHERE name='郭敬明'")  
    cursor.execute("delete from hello_author where name='韩寒'")  
    cursor.execute("select * from hello_author")  
    cursor.fetchone()  
    cursor.fetchall()
代码演示:
import os


def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'day63.settings')
    import django
    django.setup()

    from app01 import models
    # res = models.User.objects.create(name='james',age=33)
    # print(res.name)
    # print(res.age)
    # print(res.join_time)
    # print(res.uid)
    # print(res.pk)  # 无需核查主题字段真正的名字 通过pk直接获取
    # 创建数据的方式2
    # user_obj = models.User(name='green', age=25)
    # user_obj.save()
    # 查询数据
    # res = models.User.objects.filter(name='curry',age=18)
    # print(res)
    # res = models.User.objects.all()
    # print(res)
    # for i in res:
    #     print(i)
    # res = models.User.objects.filter(name='curry').first()
    # print(res)
    # res = models.User.objects.all().last()
    # print(res)
    # res = models.User.objects.get(pk=3)
    # print(res)
    # res = models.User.objects.filter(pk=3).first()
    # print(res)
    # res = models.User.objects.values('name').last()
    # print(res)
    # res = models.User.objects.all().values('name').last()
    # print(res)
    # res = models.User.objects.values_list('name','age')
    # print(res)
    # res = models.User.objects.order_by('age')  # 升序
    # res = models.User.objects.order_by('-age') # 降序
    # print(res)
    # res = models.User.objects.all().count()
    # print(res)
    # res = models.User.objects.all().distinct()  # 去重要求数据必须一毛一样
    # print(res)
    # res = models.User.objects.exclude(pk=3)
    # print(res)
    # res = models.User.objects.all().order_by('age').reverse()
    # print(res)

我的天~好神奇的双下划线查询

1.比较运算符
    字段__gt					大于
    字段__lt					小于
    字段__gte					大于等于
    字段__lte					小于等于
2.成员运算符
	字段__in					
3.范围查询(数字)
	字段__range
4.模糊查询
    字段__contains           不忽略大小写
    字段__icontains		  忽略大小写
5.日期处理
    字段__year
    字段__month
    字段__day
代码演示:
	# 查询年龄大于20的小伙
    # res = models.User.objects.filter(age__gte=20)
    # print(res)
    # res = models.User.objects.filter(age__lte=20)
    # print(res)
    # res = models.User.objects.filter(name__in=['curry','green'])
    # print(res)
    # res = models.User.objects.filter(age__range=[20,50])
    # print(res)
    # res = models.User.objects.filter(name__contains='u')
    # print(res)
    # res = models.User.objects.filter(join_time__year=2020)
    # print(res)

查看ORM底层SQL语句

1.方式1(局限性太强 不如方法2)
	如果是Queryset对象 那么可以直接点query查看SQL语句

image

2.方式2
	配置文件配置 打印所有的ORM操作对应的SQL语句 直接拷贝使用即可
    	LOGGING = {
            'version': 1,
            'disable_existing_loggers': False,
            'handlers': {
                'console':{
                    'level':'DEBUG',
                    'class':'logging.StreamHandler',
                },
            },
            'loggers': {
                'django.db.backends': {
                    'handlers': ['console'],
                    'propagate': True,
                    'level':'DEBUG',
                },
            }
        }

ORM外键字段创建

一对多
    ORM中外键字段建在多的一方 models.ForeignKey()
    会自动添加_id后缀
多对多
	ORM中有三种创建多对多字段的方式 models.ManyToManyField()
        方式1:直接在查询频率较高的表中填写字段即可 自动创建第三张关系表
        方式2:自己创建第三张关系表
        方式3:自己创建第三张关系表 但是还是要orm多对多字段做关联
一对一
	ORM中外键字段建在查询频率较高的表中 models.OneToOneField()
    	会自动添加_id后缀

django1.X 针对 models.ForeignKey() models.OneToOneField()不需要on_delete
django2.X 3.X 则需要添加on_delete参数

外键字段数据操作

models.ForeignKey(to='Publish', on_delete=models.CASCADE)
	方式1直接给实际字段添加关联数据值	 publish_id = 1
  	方式2间接使用外键虚拟字段添加数据对象 publish=publish_obj
models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
	方式1直接给实际字段添加关联数据值	 author_detail_id = 1
  	方式2间接使用外键虚拟字段添加数据对象 author_detail=authorDetail_obj
models.ManyToManyField(to='Author')
    add()
    	添加数据  括号内即可以填写数字值也可以填写数据对象 支持多个
    remove()
    	删除数据  括号内即可以填写数字值也可以填写数据对象 支持多个
    set()
    	修改数据  括号内必须是可迭代对象 
    clear()
    	清空指定数据  括号内不需要任何参数

正反向概念

ORM跨表查询口诀>>>:正向查询按外键字段 反向查询按表名小写
正向查询
	通过书查询出版社 外键字段在书表中
反向查询
	通过出版社查询书 外键字段不在出版社表中

基于对象的跨表查询(子查询)

'''基于对象的正向跨表查询'''
# 1.查询主键为3的书籍对应的出版社(书>>>出版社)
# 1.1.先根据条件查询数据对象(先查书籍对象)
book_obj = models.Book.objects.filter(pk=3).first()
# 1.2.以对象为基准 思考正反向概念(书查出版社 外键字段在书表中 所以是正向查询)
print(book_obj.publish)

# 2.查询主键为3的书籍对应的作者(书>>>作者)
# 2.1.先根据条件查询数据对象(先查书籍对象)
book_obj = models.Book.objects.filter(pk=3).first()
# 2.2.以对象为基准 思考正反向概念(书查作者 外键字段在书表中 所以是正向查询)
print(book_obj.authors)  # app01.Author.None
print(book_obj.authors.all())

# 3.查询curry的作者详情
# 3.1.先根据条件查询数据对象
author_obj = models.Author.objects.filter(name='curry').first()
# 3.2.以对象为基准 思考正反向概念
print(author_obj.author_detail)
'''基于对象的反向跨表查询'''
# 4.查询南方出版社出版的书籍
# 4.1.先拿出版社对象
publish_obj = models.Publish.objects.filter(name='南方出版社').first()
# 4.2.思考正反向
# print(publish_obj.book)
# print(publish_obj.book_set)  # app01.Book.None
print(publish_obj.book_set.all())

# 5.查询green写过的书
# 5.1.先拿作者对象
author_obj = models.Author.objects.filter(name='green').first()
# 5.2.思考正反向
# print(author_obj.book)
# print(author_obj.book_set)  # app01.Book.None
print(author_obj.book_set.all())

# 6.查询电话是111的作者
# 6.1.先拿作者详情对象
author_detail_obj = models.AuthorDetail.objects.filter(phone=111).first()
# 6.2.思考正反向
print(author_detail_obj.author)

基于双下划线的跨表查询(连表操作)

'''基于双下划线的正向跨表查询'''
# 1.查询主键为3的书籍对应的出版社名称及书名
res = models.Book.objects.filter(pk=3).values('publish__name','title')
print(res)
# 2.查询主键为3的书籍对应的作者姓名及书名
res = models.Book.objects.filter(pk=3).values('authors__name', 'title')
print(res)
# 3.查询curry的作者的电话号码和地址
res = models.Author.objects.filter(name='curry').values('author_detail__phone','author_detail__addr')
print(res)
'''基于双下划线的反向跨表查询'''
# 4.查询内蒙古出版社出版的书籍名称和价格
res = models.Publish.objects.filter(name='内蒙古出版社').values('book__title','book__price')
# print(res)

# 5.查询curry写过的书的名称和日期
res = models.Author.objects.filter(name='curry').values('book__title','book__publish_time')
# print(res)

# 6.查询电话是123的作者姓名和年龄
res = models.AuthorDetail.objects.filter(phone=123).values('author__name','author__age')
print(res)


"""
研究ORM跨表本质
# 7.查询主键为6的书籍对应的作者电话号码
res = models.Book.objects.filter(pk=6).values('authors__author_detail__phone')
    print(res)
"""
posted @ 2022-09-05 22:55  初学者-11  阅读(29)  评论(0编辑  收藏  举报