六、Django的orm之单表操作
Django模型层(一)单表操作
一、ORM
ORM是“对象-关系-映射”的简称。(Object Relational Mapping,简称ORM)
orm其实就是将类对象的语法翻译成sql语句的一个引擎
类对象 --- sql
类 -- 表
对象 -- 行
属性 -- 字段
原生sql和Python的orm代码对比:
二、Django连接数据库
在Django项目的app应用下,有一个 models.py 文件,就是专门用来写和数据库相关的代码的
-
app01 应用下 的models.py 文件中,写代码来创建一个表
from django.db import models# 创建表 class Userinfo(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=18) age = models.IntegerField() current_date = models.DateField() # 相当于: # create table userinfo( # id int primary key auto_increment, # name vachar(18), # age int, # current_data date # );
-
不连接mysql的话,默认连接的是sqlite数据库,是一个小型文档数据库,测试的时候可以用一下,但是在实际生产中很少用,而是用mysql
使用sqlite的数据库:
第一次运行时,因为没有安装sqlite的驱动,是打不开数据库的
安装驱动后再次打开,出现下面情况就是运行成功了,会显示我们制作的表结构
这个时候我们就可以添加数据了
-
连接mysql
在配置文件settings中找到:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}# 修改成: # 现在终端创建一个库 orm01 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', 'POST': 3306, # 端口 默认3306 'NAME': 'orm01', 'USER': 'root', 'PASSWORD': '123', } }
然后在项目文件夹下的 init.py 文件中加入这两句话:
import pymysql
pymysql.install_as_MySQLdb() # MySQLdb是默认的连接数据库的客户端模块,但是不支持Python3.4以上版本,所以要用pymysql把MySQLdb替换掉最后执行数据库同步指令
python manage.py makemigrations
python manage.py migrate
进入cmd终端进入mysql查看我们的表是否插入进去了:
由此可见,我们插入表的操作算是成功的完成了!!!
三、ORM表单操作
(一)、简单的增删改查
类---表
类对象 --- 一行数据
类属性 --- 字段
先创建一张表,定义四个属性:
class Student(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=18)
age = models.IntegerField()
birth_date = models.DateField()
-
增
创建记录的 方式一:
def orm(request):
student_obj = models.Student(
name = 'jiege',
age = 23,
birth_date = '1995-01-27'
)
student_obj.save()
return render(request,'myorm.html')创建记录的 方式二:
两种方式
一种 models.Student.objects.create(name='yuhao',...) # 关键字
另一种 models.Student.objects.create(**{'name':'liangdao',....}) # 字典打散def orm(request):
new_obj = models.Student.objects.create(name='yuhao',age=25,birth_date='1995-02-06')
print(new_obj) # Student object -- model对象
print(new_obj.name) # 点属性,可以获取对应字段的数据
return render(request,'myorm.html')new_obj = models.Student.objects.create(**{'name':'liangdao','age':'25','birth_date':'1994-07-22'}) print(new_obj) print(new_obj.name) return render(request,'myorm.html')
创建记录的 方式三:(批量创建,bulk_create)
def orm(request):
obj_list = []
for i in range(5):
obj = models.Student(
name=f'xiaobai{i}',
age=i+1,
birth_date='2000-01-01'
)
obj_list.append(obj)
models.Student.objects.bulk_create(obj_list)
return render(request,'myorm.html')创建记录的 方式四:(有就更新,没有就创建,update_or_create)
def orm(request):
models.Student.objects.update_or_create(
name='baobao',
age=23,
birth_date='1995-03-15'
)
return render(request,'myorm.html')添加日期的数据,要注意:
方式一:
models.Student.objects.create(birth_date='1996-11-15') # 字符串的形式方式二:
import datetime
now_date = datetime.datetime.now()
models.Student.objects.create(birth_date=now_date) # 此时插入的仍然是date类型,2019-7-19 这样
如果想打印orm转换过程中的sql,需要在settings中进行如下配置:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
-
简单的查
.all方法 查询所有的数据 返回的是queryset集合
all_objs = models.Student.objects.all()
print(all_objs)<QuerySet [<Student: Student object>, <Student: Student object>, <Student: Student object>]> -- 类似于列表 -- queryset集合
all_objs = models.Student.objects.all()
for i in all_objs:
print(i.name)jiege、yuhao.....,点属性可以取出对应的数据
.filter方法 条件查询 返回的也是queryset集合,查询不到内容,不会报错,返回一个<QuerySet []>空的queryset
objs = models.Student.objects.filter(id=2) # 找id为2的那条记录
print(objs) # <QuerySet [<Student: Student object>]>objs1 = models.Student.objects.filter(name='dazhuang')
print(objs1) # <QuerySet []> 没找到不报错,显示空objs = models.Student.objects.filter(id=2,name='yuhao')
里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系搞不定
print(objs) # <QuerySet [<Student: Student object>]>
.get方法 条件查询 返回的是model对象,而且get方法有且必须只有1个结果
obj = models.Student.objects.get(id=3) # 找id为3的那条记录
print(obj) # model对象,Student object
print(obj.name) # 点属性,可以取出对应的数据,liangdao -
删
delete方法,queryset 和model对象都可以调用
models.Student.objects.get(id=13).delete() # model对象来调用的delete方法
models.Student.objects.filter(age=1).delete() # queryset调用的delete方法
models.Student.objects.all().delete() # 删除所有
-
改
update方法,
只能queryset调用
model对象不能调用更新方法 报错信息'Student' object has no attribute 'update'
models.Student.objects.get(name='jiege').update(age=28)
# .get()返回的是model对象,不能调用update方法,会报错
models.Student.objects.filter(name='jiege').update(age=28)
# .filter()返回的是queryset对象,可以调用update方法
(二)、查询接口
-
all() 查所有
查询所有结果,结果是queryset类型 -
filter(**kwargs) 条件查询
它包含了与所给筛选条件相匹配的对象,结果也是queryset类型
models.Student.objects.filter(id=2,name='yuhao')
# 里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系搞不定models.Student.objects.filter(**{'id':2,'name':'yuhao'}) # 打散形式传参
-
get(**kwargs) 条件查询
返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,也就是model对象,返回结果有且只有一个,
如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。 -
exclude(**kwargs) 排除
排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型objects控制器和queryset集合都可以调用exclude,返回结果是queryset类型 # objects控制器调用(objects后直接加exclude方法): query = models.Student.objects.exclude(id=1) print(query) # 找到除了id是1的数据 # queryset集合调用 query = models.Student.objects.filter(age=38).exclude(id=6) print(query) # 找到age是38,除了id是6的数据
-
order_by(*field) 排序
queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型objs = models.Student.objects.all().order_by('age') # 默认是按照升序排列的,也就是按照age的升序排列 objs = models.Student.objects.all().order_by('age','id') # 多条件的,逗号隔开,先按照age升序排列,在age相同的情况下,按id升序排列 objs = models.Student.objects.all().order_by('age','-id') # 降序排列,加一个'-'就可以
-
reverse() 反转
queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型# 用在排序之后反转 query = models.Student.objects.all().order_by('age').reverse() print(query)
-
count() 计数
queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。objs = models.Student.objects.all().count() print(objs)
-
first() 第一条记录
queryset类型的数据来调用,返回第一条记录,得到的都是model对象,不是querysetobj = models.Student.objects.all().first() print(obj)
-
last() 最后一条记录
queryset类型的数据来调用,返回最后一条记录,结果为model对象类型obj1 = models.Student.objects.all().last() print(obj1)
-
exists() 判断是否包含查的数据,返回True或False
queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False空的queryset类型数据也有布尔值True和False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exits 例:all_books = models.Book.objects.all().exists() # 翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据
-
values(*field) 用的比较多 返回一个字典序列
queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。obj = models.Student.objects.filter(age=25).values() print(obj) # <QuerySet [{'id': 2, 'name': 'yuhao', 'age': 25, 'birth_date': datetime.date(1995, 2, 6)}, {'id': 3, 'name': 'liangdao', 'age': 25, 'birth_date': datetime.date(1994, 7, 22)}]> obj = models.Student.objects.filter(age=25).values('name','age') print(obj) # <QuerySet [{'id': 2, 'name': 'yuhao', 'age': 25}, {'id': 3, 'name': 'liangdao', 'age': 25 }]>
-
values_list(*field) 返回一个元组序列
它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列obj = models.Student.objects.filter(age=25).values_list('name','age') print(obj) # <QuerySet [('yuhao', 25), ('liangdao', 25)]>
-
distinct() 去重
values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录,结果还是querysetquery = models.Student.objects.all().values('age').distinct() print(query)
(三)、基于双下划线的模糊查询
1. __in=[] 值等于列表里任意一个的对象
obj = models.Student.objects.filter(age__in=[22,25,28])
print(obj)
# <QuerySet [<Student: jiege>, <Student: yuhao>, <Student: liangdao>, <Student: zhumo>]>
2. __gt 大于 __gte 大于等于
obj = models.Student.objects.filter(age__gt=25)
print(obj)
# <QuerySet [<Student: jiege>]>
# 注意,别写age>25,这种参数不支持
3. __lt 小于 __lte 小于等于
4. __range=[] 值在一个范围内
obj = models.Student.objects.filter(age__range=[22,25])
print(obj)
# sql的between and,大于等于22,小于等于25
5. __contains 包含
obj = models.Student.objects.filter(name__contains='xiao')
print(obj)
# name中包含xiao的
6. __icontains 包含,不区分大小写
obj = models.Student.objects.filter(name__contains='xiao')
print(obj)
# name中包含xiao的,不区分大小写,比如Xiao这种也能识别出来
7. __startswith 以什么开头 __endswith 以什么结尾
8. __year 找日期年份相关的 __month 月份
obj = models.Student.objects.filter(birth_date__year='1995')
print(obj)
# 找生日是1995年的人
obj1 = models.Student.objects.filter(birth_date__year='1995',birth_date__month='01')
print(obj1)
# 找生日是1995年1月份的人
.