ORM操作与查询
数据准备及环境测试
1.django有一个自带的sqlite3数据库
该数据库功能非常有限,并且针对日期类型的数据兼容性很差
2.django切换MySQL数据
2.1django1.X
import pymysql
pymysql.install_as_MySQLdb()
2.2django2.X 3.X 4.X
pip install mysqlclient
3.定义模型类
class User1(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.DateTimeField(auto_now_add=True)
'''
auto_now:每次操作数据并保存都会自动更新时间
auto_add:在创建数据时自动获取当前时间
'''
4.数据库迁移命令
makemigrations
migrate
5.在模型层测试环境准备
方式1:在任意空的py文件中准备环境
'从manage.py中复制一段'
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django01.settings')
import django
django.setup()
from app01 import models
# print(models.User1.objects.filter())
# <QuerySet [<User1: User1 object (1)>]>
if __name__ == '__main__':
main()
方式2:pycharm提供测试环境
python console命令行测试环境
ORM操作关键字
1.create()
res = models.User1.objects.create(name='barry', age=18)
print(res)
# User1 object (1)
'创造数据,返回值就是当前创建的数据对象'
res = models.User1.objects.create(name='tom', age=25)
print(res.name)
# tom
print(res.age)
# 25
print(res.uid)
# 2
print(res.pk) # 不需要知道主键字段的名字,可以通过pk直接获取
# 2
user_obj = models.User1(name='jerry', age=28)
user_obj.save()
'也可以用实例化对象任何调用save方法创建'
2.在模型类中可以定义一个__str__方法,让后续数据查询更方便查看
def __str__(self):
'对象执行打印展示(print、页面展示、数据查询)的时候自动触发'
return f'对象:{self.name}' # 该方法必须返回一个字符串
'Queryset中如果是列表套对象那么直接for循环和索引取值,不过索引取值不支持负数'
双下划线查询
1.filter()
res = models.User1.objects.filter()
'筛选数据,返回值是一个QuerySet,可以看成是列表套数据对象'
print(res)
# <QuerySet [<User1: User1 object (1)>, <User1: User1 object (2)>, <User1: User1 object (3)>]>
res = models.User1.objects.filter(name='barry')
'括号内不写查询条件则默认查询所有,括号内填写条件,并且支持多个,用逗号隔开,默认是and关系'
print(res)
# <QuerySet [<User1: User1 object (1)>]>
2.all()
res = models.User1.objects.all()
'查询所有数据,返回值是一个QuerySet,可以看成是列表套数据对象'
print(res)
# <QuerySet [<User1: User1 object (1)>, <User1: User1 object (2)>, <User1: User1 object (3)>]>
3.first()
res = models.User1.objects.filter(name='barry')
'可以使用索引,但如果值不存在会报错,所以不推荐'
print(res[0])
# User1 object (1)
res = models.User1.objects.filter().first()
'获取QuerySet中第一个数据,如果值不存在会打印None,所以推荐使用'
print(res)
# User1 object (1)
4.last()
res = models.User1.objects.filter().last()
'获取QuerySet中最后一个数据'
print(res)
# User1 object (3)
5.get()
res = models.User1.objects.get(pk=1)
'根据条件查询具体的数据对象,当条件不存在时直接报错,不推荐使用'
print(res)
# User1 object (1)
6.values()
res = models.User1.objects.all().values('name')
'指定查询字段,结果是一个QuerySet,可以看成是列表套数据对象'
print(res)
# <QuerySet [{'name': 'barry'}, {'name': 'tom'}, {'name': 'jerry'}]>
7.values_list()
res = models.User1.objects.values_list('name')
'指定查询字段,结果是一个QuerySet,可以看成是列表套数据对象'
print(res)
# <QuerySet [('barry',), ('tom',), ('jerry',)]>
8.order_by()
res = models.User1.objects.order_by('age') # 升序排列
print(res)
# <QuerySet [<User1: User1 object (1)>, <User1: User1 object (2)>, <User1: User1 object (3)>]>
res = models.User1.objects.order_by('-age') # 降序排序
print(res)
# <QuerySet [<User1: User1 object (3)>, <User1: User1 object (2)>, <User1: User1 object (1)>]>
9.count()
res = models.User1.objects.all().count()
'统计orm查询之后结果集中的数据格式'
print(res)
# 3
10.distinct()
user_obj = models.User1(name='barry', age=22)
res = models.User1.objects.values('name').distinct()
'对数据重复的数据进行去重,只有重复数据才能去重'
print(res)
# <QuerySet [{'name': 'barry'}, {'name': 'tom'}, {'name': 'jerry'}]>
11.exclude()
res = models.User1.objects.exclude(pk=1)
'对括号内的条件取反进行数据查询,结果是一个QuerySet,可以看成是列表套数据对象'
print(res)
# <QuerySet [<User1: User1 object (2)>, <User1: User1 object (3)>, <User1: User1 object (4)>]>
12.reverse()
res = models.User1.objects.all().order_by('age').reverse()
'对已经排序的结果集做颠倒'
print(res)
# <QuerySet [<User1: User1 object (3)>, <User1: User1 object (2)>, <User1: User1 object (4)>, <User1: User1 object (1)>]>
13.exists()
res = models.User1.objects.exists()
'判断查询结果是否有数据值,返回布尔值'
print(res)
# True
14.raw()
'执行SQL语句,还可以借助模块'
from django.db import connection
cursor = connection.cursor()
cursor.execute("insert into hello_author(name) VALUES ('barry')")
cursor.execute("update hello_author set name='tom' WHERE name='barry'")
cursor.execute("delete from hello_author where name='tom'")
cursor.execute("select * from hello_author")
cursor.fetchone()
cursor.fetchall()
ORM底层SQL查询方式
1.比较运算符
res = models.User1.objects.filter(age__gt=25) # 大于
print(res) # <QuerySet [<User1: 对象:jerry>]>
res = models.User1.objects.filter(age__lt=25) # 小于
print(res) # <QuerySet [<User1: 对象:barry>, <User1: 对象:barry>]>
res = models.User1.objects.filter(age__gte=25) # 大于等于
print(res) # <QuerySet [<User1: 对象:tom>, <User1: 对象:jerry>]>
res = models.User1.objects.filter(age__lte=25) # 小于等于
print(res) # <QuerySet [<User1: 对象:barry>, <User1: 对象:tom>, <User1: 对象:barry>]>
2.成员运算符
res = models.User1.objects.filter(name__in=['barry']) # 匹配返回要求的
print(res) # <QuerySet [<User1: 对象:barry>, <User1: 对象:barry>]>
3.范围查询(数字)
res = models.User1.objects.filter(age__range=(22, 25)) # 顾头也顾尾
print(res) # <QuerySet [<User1: 对象:tom>, <User1: 对象:barry>]>
4.模糊查询
res = models.User1.objects.filter(name__contains='r') # 不忽略大小写
print(res) # <QuerySet [<User1: 对象:barry>, <User1: 对象:jerry>, <User1: 对象:barry>]>
res = models.User1.objects.filter(name__icontains='R') # 忽略大小写
print(res) # <QuerySet [<User1: 对象:barry>, <User1: 对象:jerry>, <User1: 对象:barry>]>
5.日期处理
res = models.User1.objects.filter(join_time__year=2020) # 匹配返回年份的
print(res) # <QuerySet [<User1: 对象:jerry>]>
res = models.User1.objects.filter(join_time__month=8) # 匹配返回月份
print(res) # <QuerySet [<User1: 对象:jerry>]>
res = models.User1.objects.filter(join_time__day=6) # 匹配符合日期
print(res) # <QuerySet [<User1: 对象:jerry>]>
查看ORM底层SQL语句
1.方法1
如果是Queryset对象,可以直接.query查看SQL语句
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创建外键创建
1.一对多
ORM中外键字段建在多的一方models.ForeignKey()
'会自动添加_id后缀'
2.多对多
ORM中有三种创建多对多表的方法models.ManyToManyField()
方式1:直接在查询频率高的表中填写自动,自动创建第三张表
方式2:直接创建第三张关系表
方式32:直接创建第三张关系表,但是还是还要orm多对多字段做关联
3.一对一
ORM中外键字段建在查询频率较高的表中,models.OneToOneField()
'会自动添加_id后缀'
'django1.X 针对 models.ForeignKey() models.OneToOneField()不需要on_delete,django2.X 3.X 则需要添加on_delete参数'
外键字段的数据操作
1.一对多添加数据
1.1方式1直接给实际字段添加关联数据值
models.Book.objects.create(title='django基础', price=19000.98, publish_id=1)
1.2方式2间接使用外键虚拟字段添加数据对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='Golang高并发', price=19800.98, publish=publish_obj)
2.一对一添加数据
1.1方式1直接给实际字段添加关联数据值
author_detail_id = 1
1.2方式2间接使用外键虚拟字段添加数据对象
publish_obj = models.Publish.objects.filter(pk=2).first()
author_detail=authorDetail_obj
models.ManyToManyField(to='Author')
3.多对多添加数据
book_obj = models.Book.objects.filter(pk=1).first()
3.1book_obj.authors.add(1) # 朝第三张表里面添加数据
添加数据,括号内即可以填写数字值也可以填写数据对象,支持多个
3.2book_obj.authors.remove(1) # 朝第三张表里面删除数据
删除数据,括号内即可以填写数字值也可以填写数据对象,支持多个
3.2book_obj.authors.set([2, ])
修改数据,括号内必须是可迭代对象,支持多个
3.3book_obj.authors.clear()
清空指定数据,括号内不需要任何参数
正反向概念
'正反向的概念核心就在于外键字段在谁手上'
1.正向查询
通过拥有外键字段的表查询没有外键字段的表,叫正向查询
2.反向查询
通过没有外键字段的表查询有外键字段的表,叫反向查询
RM跨表查询>>>:正向查询按外键字段,反向查询按表名小写
基于对象的跨表查询(子查询)
'基于对象的正向跨表查询'
1.查询主键为1的书籍对应的出版社(书>>>出版社)
1.1.先根据条件查询数据对象(先查书籍对象)
book_obj = models.Book.objects.filter(pk=1).first()
1.2.以对象为基准,思考正反向概念(书查出版社,外键字段在书表中,所以是正向查询)
print(book_obj.publish)
# 北方出版社
2.查询主键为2的书籍对应的作者(书>>>作者)
2.1.先根据条件查询数据对象(先查书籍对象)
book_obj = models.Book.objects.filter(pk=2).first()
2.2.以对象为基准,思考正反向概念(书查作者,外键字段在书表中,所以是正向查询)
print(book_obj.authors)
# app01.Author.None
print(book_obj.authors.all())
# <QuerySet [<Author: barry>]>
3.查询jason的作者详情
3.1.先根据条件查询数据对象
author_obj = models.Author.objects.filter(name='barry').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_set.all())
# <QuerySet [<Book: Book object (2)>, <Book: Book object (4)>]>
5.查询jason写过的书
5.1.先拿作者对象
author_obj = models.Author.objects.filter(name='barry').first()
5.2.思考正反向
print(author_obj.book_set.all())
# <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>
6.查询电话是110的作者
6.1.先拿作者详情对象
author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
6.2.思考正反向
print(author_detail_obj.author)
# barry
基于双下划线的跨表查询(连表操作)
'基于双下划线的正向跨表查询'
1.查询主键为1的书籍对应的出版社名称及书名
res = models.Book.objects.filter(pk=1).values('publish__name', 'title')
print(res)
# <QuerySet [{'publish__name': '北方出版社', 'title': 'django基础'}]>
2.查询主键为3的书籍对应的作者姓名及书名
res = models.Book.objects.filter(pk=2).values('publish__name', 'title')
print(res)
# <QuerySet [{'publish__name': '南方出版社', 'title': 'Golang高并发'}]>
3.查询jason的作者的电话号码和地址
res = models.Author.objects.filter(name='barry').values('author_detail__phone', 'author_detail__addr')
print(res)
# <QuerySet [{'author_detail__phone': 110, 'author_detail__addr': '上海'}]>
'基于双下划线的反向跨表查询'
4.查询南方出版社出版的书籍名称和价格
res = models.Publish.objects.filter(name='南方出版社').values('book__title', 'book__price')
print(res)
# <QuerySet [{'book__title': 'Golang高并发', 'book__price': Decimal('19800.98')}, {'book__title': 'python数据分析', 'book__price': Decimal('29800.98')}]>
5.查询jason写过的书的名称和日期
res = models.Author.objects.filter(name='barry').values('book__title', 'book__publish_time')
print(res)
# <QuerySet [{'book__title': 'django基础', 'book__publish_time': datetime.datetime(2022, 9, 5, 14, 18, 52, 900173, tzinfo=<UTC>)}, {'book__title': 'Golang高并发', 'book__publish_time': datetime.datetime(2022, 9, 5, 14, 19, 50, 130331, tzinfo=<UTC>)}]>
6.查询电话是110的作者姓名和年龄
res = models.AuthorDetail.objects.filter(phone=110).values('author__name', 'author__age')
print(res)
# <QuerySet [{'author__name': 'barry', 'author__age': '18'}]>
标签:objects,User1,models,res,查询,ORM,print,操作
From: https://www.cnblogs.com/riuqi/p/16660020.html