表查询数据准备及测试环境搭建
sqllite3
django自带sqllite3小型数据库
该数据库功能非常有限,并且针对日期类型的数据兼容性很差
django切换MySQL数据
django1.x 版本的 需要在__init__文件导入模块
import pymysql
pymysql.install__as_MYSQLdb()
django2.x/3.x/4.x
在终端下载 pip install mysqlclient
定义模型类
class Userinfo(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)
# DateField时间字段的两个重要参数
auto_time:每次操作数据的时候都会自动更新保存当前的时间
auto_time_add:只记录第一次创建的时间,之后不人为修改的话就一直是创建的时间
数据库迁移命令
终端输入命令:
python manage.py makemigrations
python manage.py migrate
模型测试环境准备
方式1: 在任意空的py文件中准备环境
import os
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject9_5.settings') # 这两句直接在manage.py文件复制
import django
django.setup()
from app01 import models
print(models.Userinfo.objects.filter())
if __name__ == '__main__':
main()
方式2:
pycharm提供测试环境
python console命令行测试环境
表查询关键字
常见查询关键字
创建数据
# create方法
不止可以创建数据还可以返回当前创建的数据对象
可以使用对象点属性的方式获取值!
获取主键的两种方式:
对象.主键名
对象.pk 查找主键 不需要输入主键真正的名字 (适用于主键名较长或者不知道主键名的情况下)
创建数据的第二种方式:
user_obj =models.Userinfo(name= 'jason',age=88) #创建数据
user_obj.save() # 保存数据
查询所有的数据:
# filter() 括号内不填写参数 默认查询所有 filter括号内的参数可以支持多个筛选条件,逗号隔开,默认是and关系
# all() 查询所有
返回值都是QuerySet(可以看成是列表套数据对象),可以用for循环取值,也可以索引取值,但是不支持负数索引!!!
# __str__方法 对象被打印(页面展示,数据查询) 的时候执行必须返回字符串类型的数据
直接返回对象名 更方便查看数据 推荐在models里面加上
查询第一个和最后一个
first() 查找数据的第一个数据 如果没有返回None 。
models.Userinfo.objects.filter().first()
也可以用索引 如果直接用索引,没有值的话会报错!推荐使用关键字
last() 查找数据的最后一个数据 如果没有返回None
get()方法 可以通过括号内的字段名去获取数据
没有字段的时候会报错 不推荐使用
查找字段
values(字段名)筛选指定查询字段 结果是QuerySet列表套字典
可以用first或者last方法
values_list(字段名) 查询结果是QuerySet列表套元组
按字段名排序查询
order_by (默认升序)降序('-age')传多个参数的时候 第一个字段相同 自动排第二个字段 支持多个字段排序
统计个数
count() 先查询所有all().count() 统计查询的对象个数
去重
distinct() 针对重复的数据集去重(注意主键) 数据必须完全一样才可以去重 结果是QuerySet列表套字典
取反
exclude 取反 针对括号内的数据取反 结果QuerySet列表套对象
反转
reverse() 仅对排序过的数据才可以反转 对排序的结果集做颠倒 结果是QuerySet列表套对象
判断是否是数据
exists() 判断结果集是否是数字 结果返回布尔值 但是几乎不用因为所有数据自带布尔值
修改数据
models.Userinfo.objects.filter(pk=10).update(name= 'lili')
删除数据
models.Userinfo.objects.filter(pk=1).delete()
直接编写sql语句
raw()方法
导模块写入方式:
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()
双下划线查询
1.比较运算符
字段__gt 大于
字段__lt 小于
字段__gte 大于等于
字段__lte 小于等于
2.成员运算
__in
3.范围查询(针对数字)
__range
4.模糊查询
字段__contains 不忽略大小写
字段__icontains 忽略大小写
5.日期处理
字段__year
字段__month
字段__day
查看ORM底层SQL语句
# 方式一:
如果返回的是QuerySet对象 可以直接.query 查看sql语句
EXTRACT()函数:
MySQL中的此函数用于从指定日期提取零件。
此方法接受两个参数:
部分-指定要提取的部分,例如SECOND,MINUTE,HOUR,DAY,WEEK,MONTH,YEAR等。
日期-指定的提取日期。
返回值:它从指定日期返回所需的提取部分。
# 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',
},
}
}
外键创建
表关系关键字
# 一对多 models.ForeignKey()
ORM中外键字段建在多的一方
会自动添加_id后缀
# 多对多 models.ManyToManyField()
ORM中有三种创建多对多字段的方式
方式1:直接在查询频率较高的表中填写字段即可 自动创建第三张关系表
方式2:自己创建第三张关系表
方式3:自己创建第三张关系表 但是还是要orm多对多字段做关联
# 一对一 models.OneToOneField()
ORM中外键字段建在查询频率较高的表中
会自动添加_id后缀
'''
注意版本问题:
django1.X 针对 models.ForeignKey() models.OneToOneField()不需要on_delete
django2.X 3.X 则需要添加on_delete参数'''
创建表
先在models里创建四张表
book,author,publish,author_detail
分别创建字段
外键数据的增删改查
# 一对多
1.先给book表创建数据
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
在models里创建 有两种方式:
1.直接给实际字段添加关联数据值 publish_id=1
models.Book.objects.create(title='快乐星球的小王子',price=30,publish_id=1)
2.间接使用外键虚拟字段添加关联数据
publish_obj = models.Publish.objects.filter(pk=4).first() # 先获取到出版社对象
models.Book.objects.create(title='用自己的方式过一生',price=48,publish=publish_obj)
添加数据报错:
django.db.utils.IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails
解决办法: 在settings的DATABASES里添加一条数据
'OPTIONS': {"init_command": "SET foreign_key_checks = 0;"}
# 一对一
给作者关联数据
author_datail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
在models里创建 有两种方式
1.直接给实际字段添加关联数据值
2.间接使用外键虚拟字段添加关联数据
# 多对多 (重要) 主要操作第三张表 增删改查
authors = models.ManyToManyField(to='Author')
利用第三张表的虚拟名称
book对象.外键字段.add() 添加数据 既可以放数字 也可以放对象
book_obj = models.Book.objects.filter(pk=7).first()
book_obj.authors.add(4)
book_obj = models.Book.objects.filter(pk=5).first()
author_obj = models.Author.objects.filter(pk=1).first()
book_obj.authors.add(author_obj)
book对象.外键字段.remove() 删除数据 既可以放数字 也可以放对象
book_obj.authors.remove(1)
book对象.外键字段.set() 修改数据 括号内必须是可迭代对象 iterable_obj
book_obj.authors.set([1,3]) # set()括号内只可以放支持迭代的对象 【相当于删除加新增】
book_obj.authors.clear() 清空指定数据 括号不需要任何参数
book_obj.authors.clear() # 清除书籍对象对应的所有作者
2.以对象为基准 思考正反向概念 (思考什么时候会出现None)
跨表查询
正反向概念
1.正反向概念核心就在于外键字段在哪张表
在有外键字段的表查询 正向查询 按外键字段
没有外键字段的表查询 反向查询 按表名小写加_set
基于对象的跨表查询(子查询)
# 正向查询
1.查询主键为1的书籍对应的出版社名称(书查出版社) 一对多
1.根据条件查询数据对象
book_obj = models.Book.objects.filter(pk=1).first()
2.以对象为基准 思考正反向概念
print(book_obj.publish.name)
2.查询主键为3的书籍对应的作者 多对多
1.根据条件查询数据对象
book_obj = models.Book.objects.filter(pk=3).first()
2.以对象为基准 思考正反向概念 (思考什么时候会出现None)
'''因为多对多是有多个作者,所以返回None 需要自己点all'''
print(book_obj.authors.all())
3.查询jerry作者的详情 一对一
1.根据条件查询数据对象
author_obj = models.Author.objects.filter(name='jerry').first()
2.以对象为基准 思考正反向概念
print(author_obj.author_datail)
# 反向查询
1.查询上海出版社出版的书籍 多对多
1.先拿出版社对象(如果是拿的是对象一定要点first)
publish_obj = models.Publish.objects.filter(name='上海出版社').first()
2.思考正反向 (结果打印None需要点all)、
print(publish_obj.book_set.all())
2.查询summer写过的书籍 一对多
1.先拿作者对象
author_obj = models.Author.objects.filter(name='summer').first()
2.思考正反向
print(author_obj.book_set.all())
3.查询电话是111111的作者 一对一
1.先查询作者详情对象
author_detail_obj = models.AuthorDetail.objects.filter(phone=11111).first()
2.思考正反向 (不需要加set)
print(author_detail_obj.author)
# 总结:一对多或多对多需要反向查询需要加_set点all(),一对一不需要
基于双下划线的多表查询(连表查询)
# 正向查询
1.查询主键为3的书籍对应的出版社名称(书查出版社) 一对多 # 只能写一行代码
res = models.Book.objects.filter(pk=3).values('publish__name')
2.查询主键为3的书籍对应的作者 多对多
# 用现有的条件点现有的表
res=models.Book.objects.filter(pk=3).values('authors__name','title')
3.查询tom作者的详情 一对一
res = models.Author.objects.filter(name='tom').values('author_datail__phone')
# 反向查询
1.查询北京出版社出版的书籍名称和价格 多对多
res = models.Publish.objects.filter(name= '北京出版社').values('book__price','book__title')
2.查询summer写过的书籍名称和日期 一对多
res = models.Author.objects.filter(name='summer').values('book__title','book__publish_time')
3.查询电话是11111的作者 一对一
res = models.AuthorDetail.objects.filter(phone=11111).values('author__name')