Django ORM单表操作
Django 测试环境搭建
注意pycharm链接数据库都需要提前下载对应的驱动,自带的sqlite3对日期格式数据不敏感,如果后续业务需要使用日期辅助筛选数据那么不推荐使用sqlite3
搭建方式
- 任意创建一个py文件,在该文件内书写固定的配置
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day06.settings")
import django
django.setup()
- 直接使用pycharm提供的
python console
ORM 创建表
# Mysql配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'orm_simple',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': 'root',
'CHARSET':'utf8'
}
}
'''__init__.py'''
import pymysql
pymysql.install_as_MySQLdb()
创建表
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5,decimal_places=2)
publish = models.CharField(max_length=32)
publish_data = models.DateField() # 出版时间
# 路由
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/', views.book),
]
ORM 添加数据
有两种添加数据的方式:
- 方式一:模型类实例化对象
- 方式二:通过 ORM 提供的 objects 提供的方法 create 来实现(推荐)
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
'''添加数据的两种方式'''
# 方式1
book_obj = models.Book(title='Python',price='99',publish='Hammer出版社',publish_data='2022-2-2')
book_obj.save()
# 方式2
models.Book.objects.create(title='Java',price='88',publish='Hans出版社',publish_data='2021-2-1')
return HttpResponse('<p>数据添加成功</p>')
ORM 查询数据
all 查询
all()
方法查询所有数据,返回一个QuerySet对象,类似list,可以通过索引来获取列表中的对象,这里不支持负索引
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
book_obj = models.Book.objects.all()
print(book_obj) # <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>
print(book_obj[0]) # Book object (1)
print(book_obj.first()) # Book object (1) 等价于[0]
print(book_obj.first().title) # Python 获取值
return HttpResponse('<p>数据查询成功</p>')
filter 查询
filter() 方法用于查询符合条件的数据
返回的是 QuerySet 类型数据,类似于 list,里面放的是满足条件的模型类的对象,可用索引下标取出模型类的对象;
def book(request):
book_obj = models.Book.objects.filter(pk=2)
print(book_obj)
print(book_obj.first().title) # JavaScript
book_obj1 = models.Book.objects.filter(title='JavaScript',price='99')
print(book_obj1.first().pk) # 2
return HttpResponse('<p>数据查询成功</p>')
exclude 取反查询
exclude() 方法用于查询不符合条件的数据,返回的是 QuerySet 类型数据,类似于 list,里面放的是不满足条件的模型类的对象,可用索引下标取出模型类的对象;
def book(request):
book_obj = models.Book.objects.exclude(pk=2)
print(book_obj) # <QuerySet [<Book: Python>, <Book: C>, <Book: PHP>, <Book: C++>, <Book: 数据结构>]>
for i in book_obj.all():
print(i.title) # Python C PHP C++ 数据结构
return HttpResponse('<p>数据查询成功</p>')
get 查询
get() 方法用于查询符合条件的返回模型类的对象符合条件的对象只能为一个,如果符合筛选条件的对象超过了一个或者没有一个都会抛出错误
区别filter()如果获取不到符合条件的数据,返回一个空对象,不报错
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
book_obj = models.Book.objects.get(pk=1)
print(book_obj)
return HttpResponse('<p>数据查询成功</p>')
order_by 排序
order_by() 方法用于对查询结果进行排序,返回的是 QuerySet类型数据,类似于list,里面放的是排序后的模型类的对象,可用索引下标取出模型类的对象
- 参数的字段名要加引号
- 降序为在字段前面加个负号 -
def book(request):
# 升序排序
book_obj = models.Book.objects.order_by('id')
for i in book_obj:
print(i.title) # Python JavaScript C PHP C++ 数据结构
# 降序排序
book_obj1 = models.Book.objects.order_by('-id')
for i in book_obj1:
print(i.title) # 数据结构 C++ PHP C JavaScript Python
return HttpResponse('<p>数据查询成功</p>')
**reverse 反转 **
reverse() 方法用于对查询结果进行反转,返回的是 QuerySe t类型数据,类似于 list,里面放的是反转后的模型类的对象,可用索引下标取出模型类的对象
使用反转函数前先排序
def book(request):
# 按照价格升序排列:降序再反转
books = models.Book.objects.order_by("-price").reverse()
return HttpResponse("<p>查找成功!</p>")
count 汇总数量
count() 方法用于查询数据的数量返回的数据是整数
def book(request):
book_obj = models.Book.objects.count()
print(book_obj) # 查询所有数据的数量>>>6
book_obj1 = models.Book.objects.filter(price=200).count() # 查询符合条件数据的数量
return HttpResponse('<p>数据查询成功</p>')
exists 判断
exists() 方法用于判断查询的结果 QuerySet 列表里是否有数据,返回的数据类型是布尔,有为 true,没有为 false。
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
books = models.Book.objects.exists()
# True
books = models.Book.objects.count().exists()
# 报错,判断的数据类型只能为QuerySet类型数据,不能为整型
books = models.Book.objects.first().exists()
# 报错,判断的数据类型只能为QuerySet类型数据,不能为模型类对象
return HttpResponse("<p>查找成功!</p>")
values 查询字段
返回的是 QuerySet 类型数据,类似于 list,里面不是模型类的对象,而是一个可迭代的字典序列,字典里的键是字段,值是数据
def book(request):
book_obj = models.Book.objects.values('price','title')
print(book_obj) # 返回所有price和title字段,以列表套字典的形式
# <QuerySet [{'price': Decimal('99.00'), 'title': 'Python'}]
book_obj1 = models.Book.objects.filter(pk=1).values('title')
print(book_obj1,book_obj[0].get('title')) # <QuerySet [{'title': 'Python'}]> Python
return HttpResponse('<p>数据查询成功</p>')
values_list 查询部分字段
values_list() 方法用于查询部分字段的数据,values_list() 方法用于查询部分字段的数据
def book(request):
book_obj = models.Book.objects.values_list('price','title')
print(book_obj) # 返回所有price和title字段,以列表套元组的形式
# <QuerySet [(Decimal('99.00'), 'Python')]
for title in book_obj:
print(title[1]) # 获取所有title
return HttpResponse('<p>数据查询成功</p>')
values和values_list区别
- values查询返回的结果是列表套字典的形式,字段名和数据都能够获取到
- values_list查询返回的结果是列表套元组的形式,只返回数据
distinct 去重
distinct() 方法用于对数据进行去重,返回的是 QuerySet 类型数据
注意:
- 对模型类的对象去重没有意义,因为每个对象都是一个不一样的存在(主键不一样),去重的前提是数据必须是一模一样
- distinct() 一般是联合 values 或者 values_list 使用
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
# 查询一共有多少个出版社
books = models.Book.objects.values_list("publish").distinct() # 可以去重
books = models.Book.objects.distinct()
# 对模型类的对象去重没有意义,因为每个对象都是一个不一样的存在,主键不一样
return HttpResponse("<p>查找成功!</p>")
ORM 双下划线方法
__in
类似sql的成员运算,用于读取区间,= 号后面为列表
注意:filter 中运算符号只能使用等于号 = ,不能使用大于号 > ,小于号 < ,等等其他符号
- 格式:字段__in = [a,b]
def book(request):
book_obj = models.Book.objects.filter(price__in=[100,300])
print(book_obj) # <QuerySet [<Book: Book object (2)>, <Book: Book object (22)>]>
return HttpResponse('<p>数据查询成功</p>')
__gt __gte
大于、大于等于
# 价格大于100的数据
book_obj = models.Book.objects.filter(price__gt=100)
# 价格大于等于100的数据
book_obj = models.Book.objects.filter(price__gte=100)
__lt __lte
小于、小于等于
# 价格小于100的数据
book_obj = models.Book.objects.filter(price__lt=100)
# 价格小于等于100的数据
book_obj = models.Book.objects.filter(price__lte=100)
__range
表示范围,在···之间,类似sql的between··and,左闭右区间,= 号后面为两个元素的列表
# 价格在100到200之间的数据
book_obj = models.Book.objects.filter(price__range=[100,300])
__contains
包含关系,=号后面为字符串,类似sql的模糊查询,LIKE
# 查询包含Py字符的书名
book_obj = models.Book.objects.filter(title__contains='Py')
__icontains
不区分大小写,和
contains
一样
# 查询包含Py字符的书名
book_obj = models.Book.objects.filter(title__contains='py')
__startswith
查询以指定字符开头,= 号后面为字符串
book_obj = models.Book.objects.filter(title__startswith='P')
__endswith
查询以指定字符结尾,=号后面为字符串
book_obj = models.Book.objects.filter(title__endswith='构')
__year
__year 是 DateField 数据类型的年份,= 号后面为数字
# 2022年出版的数据
book_obj = models.Book.objects.filter(publish_date__year=2022)
__month
查询月份
# 3月出版的数据
book_obj = models.Book.objects.filter(publish_date__month=3)
__day
__day 是DateField 数据类型的天数,= 号后面为数字
# 所有17号出版的数据
book_obj = models.Book.objects.filter(publish_date__day=17)
ORM 删除数据
方式一:使用模型类的 对象.delete()
返回值:元组,第一个元素为受影响的行数
book_obj=models.Book.objects.filter(pk=8).first().delete()
方式二:使用 QuerySet 类型数据.delete()(推荐)
返回值:元组,第一个元素为受影响的行数。
books=models.Book.objects.filter(pk__in=[1,2]).delete()
注意:
- Django 删除数据时,会模仿 SQL约束 ON DELETE CASCADE 的行为,也就是删除一个对象时也会删除与它相关联的外键对象;
- delete() 方法是 QuerySet 数据类型的方法,但并不适用于 Manager 本身。也就是想要删除所有数据,不能不写 all;
ORM 修改数据
方式一:
模型类的对象.属性 = 更改的属性值
模型类的对象.save()
def book(request):
book_obj = models.Book.objects.filter(pk=23).first()
print(book_obj)
book_obj.title='如何傍富婆,从入门到入赘'
book_obj.save()
return HttpResponse('<p>入赘成功</p>')
方式二:QuerySet 类型数据.update(字段名=更改的数据)(推荐)
返回值:整数,受影响的行数
def book(request):
book_obj = models.Book.objects.filter(pk=23).update(title='人活一口气,打死不入赘')
return HttpResponse(book_obj) # 1
ORM 逆转到 SQL
方式一:
如果想打印orm转换过程中的sql,需要在settings中进行如下配置:
'''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',
},
}
}
ps:本质是日志的监控,可以在test下测试
方式二:使用对象.query获取原生SQL()
from app01 import models
res = models.Book.objects.filter(pk=2)
print(res.query)
'''
SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish`, `app01_book`.`publish_date` FROM `app01_book` WHERE `app01_book`.`id` = 2
'''