Django之ORM操作Mysql
一、单表操作
# 单表查询操作基本方法
class BookList(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2) # 总共8位,小数占2位
publist_date = models.DateField() # DateField年月日,DateTimeField详细时间 #单独测试models.py文件
# 将manage.py中前4行拷贝到一个新的test.py文件中
import os
import sys if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day20.settings")
import django
django.setup()
from app01 import models
# 插入语句
# book_obj = models.BookList.objects.create(title="三国演义",price=1123.22,publist_date='2019-08-28')
# import datetime
# ctime = datetime.datetime.today()
# book_obj = models.BookList.objects.create(title="红楼梦",price=1666.22,publist_date=ctime)
# print(book_obj) # BookList object # 更新数据
# models.BookList.objects.filter(title="三国演义").update(price=1123.22)
# queryset方法都是批量更新操作 # 查询
# print(models.BookList.objects.all()) # <QuerySet [<BookList: 三国演义>, <BookList: 红楼梦>]>
# print(models.BookList.objects.filter(pk=1)) # <QuerySet [<BookList: 三国演义>]> # 推荐使用
# # get获取到的就是数据对象本身,但是条件不满足的时候会直接报错,不推荐使用
# print(models.BookList.objects.get(pk=3)) # 红楼梦 # 删除
# models.BookList.objects.filter(pk=1).delete() # 更多查询方法
# exclude取反
# print(models.BookList.objects.exclude(pk=1)) # values 拿对应的字段,返回的是列表套字典
# print(models.BookList.objects.values('title','price'))
# <QuerySet [{'title': '三国演义', 'price': Decimal('1123.22')}, {'title': '红楼梦', 'price': Decimal('1666.22')}]> # value_list 返回的是列表套元组
# print(models.BookList.objects.values_list('title','price'))
# <QuerySet [('三国演义', Decimal('1123.22')), ('红楼梦', Decimal('1666.22'))]> # order by 查询结果排序 默认升序
# print(models.BookList.objects.order_by('price'))
# <QuerySet [<BookList: 三国演义>, <BookList: 红楼梦>]>
# 降序
# print(models.BookList.objects.order_by('price').reverse()) # 去重:去重的前提是:数据必须是完全一样的
# print(models.BookList.objects.filter(title="三国演义").values('title','price').distinct())
# <QuerySet [{'title': '三国演义', 'price': Decimal('1123.22')}]> # count()
# print(models.BookList.objects.all().count()) # first/last
# print(models.BookList.objects.first())
# print(models.BookList.objects.last()) # exists
# print(models.BookList.objects.filter(pk=2).exists())
# 13个必须会的操作
# 返回QuerySet对象的方法有
all() 查询所有结果
filter() 它包含了与所给筛选条件相匹配的对象
exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
order_by()
reverse(): 对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)
distinct(): 从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重 # 特殊的QuerySet
values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 # 返回具体对象的
get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误
first() : 第一条记录
last() : 最后一条记录 # 返回布尔值的方法有
exists(): 如果QuerySet包含数据,就返回True,否则返回False # 返回数字的方法有
count(): 返回数据库中匹配查询(QuerySet)的对象数量
二、单表查询之双下划线操作
models.Tb1.objects.filter(id__lte=10, id__gt=1) # 获取id大于1 且 小于等于10的值 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and 类似的还有:startswith,istartswith, endswith, iendswith
date字段还可以:
models.Class.objects.filter(datetime__year=2017)
date字段可以通过在其后加__year,__month,__day等来获取date的特点部分数据
# date
#
# Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
# Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) # year
#
# Entry.objects.filter(pub_date__year=2005)
# Entry.objects.filter(pub_date__year__gte=2005) # month
#
# Entry.objects.filter(pub_date__month=12)
# Entry.objects.filter(pub_date__month__gte=6) # day
#
# Entry.objects.filter(pub_date__day=3)
# Entry.objects.filter(pub_date__day__gte=3) # week_day
#
# Entry.objects.filter(pub_date__week_day=2)
# Entry.objects.filter(pub_date__week_day__gte=2)
# 需要注意的是在表示一年的时间的时候,我们通常用52周来表示,因为天数是不确定的
三、图书管理系统表设计
表关系
一对一
一对多
多对多
ps:站在两边判断是否可以同时有多个对方
如果都可以 那么就是多对多
如果是单向的一对多 那么就是一对多
如果都不是 要么没有任何关系 要么就是一对一 Book 书籍
Publish 出版社
Author 作者
AuthorDetail 作者详情 书和出版社 就是一个一对多
书和作者 多对多
作者和作者详情 一对一
# models.py 表结构
"""
一对多 :外键字段 通常建在多的一方
多对多 :外键字段 无论建在哪一方都可以,但是推荐建在查询频率较高的表
一对一 :外键字段 无论建在哪一方都可以,但是推荐建在查询频率较高的表
"""
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
# 出版社外键
publish = models.ForeignKey(to='Publish') # 默认关联的就是Publist表的主键字段
# 作者外键
authors = models.ManyToManyField(to='Author') # 默认关联的就是Author表的主键字段
# 一对多外键字段,在书写的时候,orm会自动加_id后缀
"""多对多字段是虚拟字段,不会在表中展示出来
只是用来告诉django orm 自动 创建书籍和作者的第三张表
还可以跨表查询的时候提供方便
""" class Publish(models.Model):
name = models.CharField(max_length=32)
email = models.EmailField
addr = models.CharField(max_length=32) class Author(models.Model):
name = models.CharField(max_length=32)
age = models.CharField(max_length=3)
male = models.CharField(max_length=1)
# 一对一
# 一对一外键字段,在书写的时候,orm会自动加_id后缀
author_detail = models.OneToOneField(to='AuthorDetail') class AuthorDetail(models.Model):
phone = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
#数据自己伪造就可以
""" ORM 联表操作 """
# 外键字段的增
# models.Book.objects.create(title='三国演义',price='98.5',publish_id=1)
# models.Book.objects.create(title='红楼梦',price='128.88',publish_id=1)
# models.Book.objects.create(title='密卷',price='58',publish_id=4)
# publish_obj = models.Publish.objects.filter(pk=2).first()
# models.Book.objects.create(title='西游记',price='90',publish=publish_obj) # 改
# models.Book.objects.filter(pk=1).update(publish_id=3)
# 虚拟对象直接传字段
# publish_obj = models.Publish.objects.filter(pk=2).first()
# models.Book.objects.filter(pk=1).update(publist=publish_obj) # 作者和书籍绑定关系
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.add(1) # 在第三张表book_authors中,添加书籍和作者的关系,也可以添加2条add(1,2),2本书是这个作者写的
# author_obj1 = models.Author.objects.filter(pk=1).first()
# author_obj2 = models.Author.objects.filter(pk=2).first()
# book_obj.authors.add(author_obj1,author_obj2)
"""
add既支持传数字,也支持传对象,两者也都可以是多个
"""
# 改
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.set([2,])
"""
set既支持传数字,也支持传对象,两者也都可以是多个
注意:传入的格式必须是可迭代对象
""" # 删
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.remove(2)
"""
remove既支持传数字,也支持传对象,两者都可以是多个
"""
# 清空
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear() # 清空当前数据所有的关联信息
"""
clear()内不需要传任何参数
"""
四、Django终端打印SQL语句
# settings.py文件中,加了这段话后,会将django执行的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',
},
}
} # SELECT `app01_book`.`title` FROM `app01_publish` INNER JOIN `app01_book` ON (`app01_publish`.`id` = `app01_book`.`publish_id`)
WHERE (`app01_publish`.`name` = '南方出版社' AND `app01_book`.`price` > '19') LIMIT 21; args=('南方出版社', '19')
五、ORM多表查询
# 正向与反向的概念解释
正向查询按字段(字典建表时的关联字段)
反向查询按表名小写... # 一对一
# 正向:author---关联字段在author表里--->authordetail 按字段
# 反向:authordetail---关联字段在author表里--->author 按表名小写
# 查询jason作者的手机号 正向查询
# 查询地址是 :山东 的作者名字 反向查询 # 一对多
# 正向:book---关联字段在book表里--->publish 按字段
# 反向:publish---关联字段在book表里--->book 按表名小写_set.all() 因为一个出版社对应着多个图书 # 多对多
# 正向:book---关联字段在book表里--->author 按字段
# 反向:author---关联字段在book表里--->book 按表名小写_set.all() 因为一个作者对应着多个图书
5.1 基于对象的跨表查询:子查询
# 基于对象的跨表查询
# 查询书籍id为1的出版社名称(正向)
# book_obj = models.Book.objects.filter(pk=1).first()
# print(book_obj.publish) # Publish object
# print(book_obj.publish.name) #南方出版社
# 查询南方出版社出版过的书的名字(反向)
# publish_obj = models.Publish.objects.filter(name="南方出版社").first()
# print(publish_obj.book_set) # app01.Book.None 意味着语句没写全,_set说明有多个结果
# print(publish_obj.book_set.all()) # <QuerySet [<Book: Book object>, <Book: Book object>]> # 查询作者simon的手机号(正向)
# author_obj = models.Author.objects.filter(name="simon").first()
# print(author_obj.author_detail.phone)
# 根据手机号150查作者(反向)
# authordetail_obj = models.AuthorDetail.objects.filter(phone=150).first()
# print(authordetail_obj.author.name)
# 反向查询:根据作者simon查询手机号
res1 = models.AuthorDetail.objects.filter(author__name='simon').values('phone')
print(res1)
# 反向查询:查询年龄和手机号
res =models.AuthorDetail.objects.filter(author__name='simon').values('author__age','phone')
# 多对多
# 查询书籍ID为1的作者姓名
# book_obj = models.Book.objects.filter(pk=1).first()
# print(book_obj.authors.all()) # <QuerySet [<Author: Author object>, <Author: Author object>]>
# 查询作者ID为1的写的书(反向)
# author_obj = models.Author.objects.filter(pk=1).first()
# print(author_obj.book_set.all())
5.2 基于双下划线的多表查询
# 查询书籍id为1的作者的姓名:2张表没有直接关联,需要通过book_authors来关联(正向)
res1 = models.Book.objects.filter(id=1).values('authors')
print(res1) # <QuerySet [{'authors': 2}, {'authors': 4}]> 查询到作者ID
res = models.Book.objects.filter(id=1).values('authors__name')
print(res) # 作者名:<QuerySet [{'authors__name': 'jace'}, {'authors__name': 'once'}]> 作者姓名是once写过的书的价格(反向)
res = models.Author.objects.filter(name='once').values('book__price','book__title')
print(res) # <QuerySet [{'book__price': '98.5', 'book__title': '三国演义'}]> # 查询书籍id为1的出版社addr(正向)
res = models.Book.objects.filter(id=1).values('publish__addr') # 这里的publish不是表面小写而是字段
print(res) # <QuerySet [{'publish__addr': '上海'}]> # 通过出版社id=1找出版过的书(反向)
res = models.Publish.objects.filter(id=1).values('book__title')
print(res) # <QuerySet [{'book__title': '红楼梦'}]> # 查询红楼梦作者的电话号码(正向)
res = models.Book.objects.filter(title="红楼梦").values('authors__author_detail__phone')
print(res) # <QuerySet [{'authors__author_detail__phone': '150'}]> # 查询作者电话号码是150出版过的书籍(反向)
res = models.AuthorDetail.objects.filter(phone=150).values('author__book__title')
print(res) # <QuerySet [{'author__book__title': '红楼梦'}, {'author__book__title': '考卷'}]>
5.3 联合查询
# 查询北方出版社出版的的价格大于19的书
res = models.Book.objects.filter(price__gt='19',publish__name="北方出版社")
print(res) # <QuerySet [<Book: Book object>]> # 查询南方出版社出版过的书,且价格大于19(反向)
res = models.Publish.objects.filter(name="南方出版社",book__price__gt=19).values('book__title')
print(res) # <QuerySet [{'book__title': '三国演义'}, {'book__title': '18岁的天空'}]>
5.4 聚合查询与分组查询
from django.db.models import Avg,Sum,Max,Min,Count
# 聚合查询
# 请所有书籍的平均价格
res = models.Book.objects.all().aggregate(Avg("price"))
print(res) # 分组查询(group_by)
# 统计每本书作者的个数
book_list = models.Book.objects.all().annotate(author_num=Count("authors"))
for obj in book_list:
print(obj.author_num) # 统计每个出版社卖的最便宜的书
res = models.Publish.objects.annotate(min_price=Min("book__price"))
print([i.min_price for i in res ])
# for obj in res:
# print(obj.min_price) #第二种方法:
res = models.Book.objects.values("publish__name").annotate(min_price=Min("price"))
print(res)
# <QuerySet [{'publish__name': '工业出版社', 'min_price': '128.88'}, {'publish__name': '北方出版社', 'min_price': '90'}, {'publish__name': '南方出版社', 'min_price': '38'},
# {'publish__name': '武汉出版社', 'min_price': '38'}]> # 统计不只一个作者的书
res = models.Book.objects.annotate(authors_num=Count("authors")).filter(authors_num__gt=1)
print(res)
# <QuerySet [<Book: Book object>]>
5.5 F 与 Q
# F查询:查询的条件左右两边都来自于数据库而非你自己定义
# F可以帮我们取到表中某个字段对应的值来当作我的筛选条件,而不是我认为自定义常量的条件了,实现了动态比较的效果:F 可以帮我们实现同一表中2个字段进行比较 from django.db.models import F,Q
# 查询卖出数大于库存数的书籍
# sell_book和kc_book为字段名
res = models.Book.objects.filter(sell_book__gt=F('kc_book')).values('title')
print(res)
# 将每个商品的价格提高50元
res2 = models.Book.objects.update(price=F('price') + 50) # Q查询:能够将filter内部默认的and关系,转换成 与或非
# 逗号 默认也是 与 的关系
# 与& 或| 非~
# 查询书籍名字是西游记或价格是140的书籍
res = models.Book.objects.filter(Q(title="西游记")|Q(price=140)).values('title')
# res = models.Book.objects.filter(title="西游记",price=140).values('title')
print(res) # 非 ~Q
# 查询书籍价格不是140的书籍名
res1 = models.Book.objects.filter(~Q(price=140)).values("title")
print(res1)
多对多表关系三种创建方式
1.全自动:ManyToManyField()自动创建第三张表
authors = models.ManyToManyField(to='Author')
让django orm自动帮你创建第三张表
好处:不需要自己手动添加
坏处:表字段的扩展性极差 只会帮你建外键字段 其他额外字段一概无法创建 2.纯手动(了解):无法使用跨表查询,必须自己一个表一个表手动查找
class Book(models.Model):
name = ...
class Author(models.Model):
name = ...
class Book2Author(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author') 3.半自动:可以使用跨表查询,与全自动一样
优点:可以自己加额外的字段
class Book(models.Model):
name = ...
authors = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author'))
class Author(models.Model):
name = ...
# 如果外键建在这张表
# books = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('author','book'))
class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
create_time = ...
info = ...
Django之ORM操作Mysql的更多相关文章
- 【Django】ORM操作MySQL数据库遇到的一些问题
关于查询操作: 1.exact和iexact exact相当于= iexact相当于like(但是这里的like和数据库的不一样,没有给后面条件加上%%所以这里like和=的作用相似) artic ...
- Django之ORM操作
Django之ORM操作 前言 Django框架功能齐全自带数据库操作功能,本文主要介绍Django的ORM框架 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计 ...
- Django之ORM操作(***)
Django之ORM操作(***) http请求的流程: url--> 视图view(模板+数据库) --> ORM的功能: 可以转换SQL语句,并做操作. ORM操作数据表: -创建表: ...
- 【Django】ORM操作#1
目录 一.介绍 概念 由来 优势 劣势 总结 二.Django中的ORM Django项目使用MySQL Model 快速入门 1. AutoField 2. IntegerField 3. Char ...
- Django之ORM操作(聚合 分组、F Q)
Django之ORM操作(聚合 分组.F Q) 聚合 aggregate()是QuerySet的一个终止子句,也就是说,他返回一个包含一些键值对的字典,在它的后面不可以再进行点(.)操作. 键的名 ...
- 【Django】ORM操作#2
目录 必知必会的13条查询方法 单表查询之神奇的双下划线 一对多 ForeignKey 多对多 ManyToManyField 在Python脚本中调用Django环境 Django终端打印SQL语句 ...
- golang利用beego框架orm操作mysql
GO引入orm框架操作mysql 在beego框架中引入orm操作mysql需要进行的步骤: 第一步:导入orm框架依赖,导入mysql数据库的驱动依赖 import ( "github.c ...
- django的orm操作优化
django的orm操作优化 models.py from django.db import models class Author(models.Model): name = models.Char ...
- Django的ORM操作
ORM操作 select * from tb where id > 1 # 对应关系 models.tb.objects.filter(id__gt=1) models.tb.objects.f ...
- Django 之ORM操作
1.什么是ORM? 全称关系对象映射Object Relational Mapping(简称ORM),是通过描述面向对象与数据库之间的对应的元数据,将对象持久化的更新到数据库中. 有了ORM,就不需要 ...
随机推荐
- 风场可视化学习笔记:openlayers
最近在弄地图控件方面的东西,这里分享一个我找到的一个添加风场的教程和demo,需要对大家有所帮助(以下为转载内容)载于https://blog.csdn.net/u010065726/article/ ...
- elasticsearch使用painless的一些简单例子
目录 1.背景 2.准备数据 2.1 mapping 2.2 插入数据 3.例子 3.1 (update)更新文档 id=1 的文档,将 age 加 2岁 3.2 (update_by_query)如 ...
- vue2中安装vuex
2022年2月7日,vue3成为默认版本,npm i vue安装的直接就是vue3了 npm i -vuex 安装的是vuex4 vuex4只能在vue3中使用 vue2中,要用vuex3版本,安装 ...
- Spring Cloud导入Spring Boot项目当作子模块微服务IDEA不识别子module问题
1.在父工程下面引入module. <modules> <module>study-design-mode</module> </modules> 2. ...
- 创业:大模型RAG系统三个月的开发心得和思考
1. 前言 自从和员外上家公司离职后,我们就自己搞公司投入到了RAG大模型的AI产品应用的开发中,这中间有一个春节,前后的总时间大概是三个月左右,在这三个月期间,基本是昼夜兼程啊,到今天3月底结束,产 ...
- 从零开始学Spring Boot系列-集成MyBatis-Plus
在Spring Boot应用开发中,MyBatis-Plus是一个强大且易于使用的MyBatis增强工具,它提供了很多实用的功能,如代码生成器.条件构造器.分页插件等,极大地简化了MyBatis的使用 ...
- #状压dp#洛谷 3959 [NOIP2017 提高组] 宝藏
题目 选定一个起点 \(S\),找到一棵生成树,最小化 \[\sum_{i=1}^n dep_i\times dis_i \] \(n\leq 12\) 分析 设 \(dp[d][S]\) 表示当前树 ...
- 圈重点!一图读懂OpenHarmony技术日
- OpenHarmony 3.2 Beta多媒体系列——音视频播放框架
一.简介 媒体子系统为开发者提供一套接口,方便开发者使用系统的媒体资源,主要包含音视频开发.相机开发.流媒体开发等模块.每个模块都提供给上层应用对应的接口,本文会对音视频开发中的音视频播放框架做一 ...
- DevEco Studio新特性分享-跨语言调试,让调试更便捷高效
原文:https://mp.weixin.qq.com/s/JKVLQXu1z1zAoF5q49YEGg,点击链接查看更多技术内容. HUAWEI DevEco Studio是开发Harmony ...