Django--model-数据库操作
https://www.cnblogs.com/xiaonq/p/10959010.html#i2
https://www.cnblogs.com/wupeiqi/articles/5246483.html
一、操作数据库表
1.基础操作
数据的增加
方法一:
#使用create方法添加数据
user = User.objects.create(name='root', age=12, home='北京市', class_room_id=1)
方法二:
#使用save保存数据
obj = User(name='root', age=13, home='北京市', class_room_id=1)
obj.save()
方法三:
#传入多条数据需要添加**号 类似于*args,**kwargs
dic = {'name':'root', 'age':12, 'home':'北京市', 'class_room_id':1}
usesr=User.objects.create(**dic)
数据的删除
方法一:
#一般都是从前端获取到对应数据id/pk进行对应删除
user = User.objects.get(id=17).delete()
方法二:
user=User.objects.all().delete() # 删除所有
方法三:
user=User.objects.filter(name='seven').delete() # 删除指定条件的数据
数据的修改
方法一:
user = User.objects.get(name='王五') #找到要修改的数据 一般使用id来查找 主键唯一
user.name = '猪悟能' #定义修改的数据
user.save()
方法二:
User.objects.all().update(age=12) #将所有用户的年纪修改成12
方法三:
# 将指定条件的数据更新,均支持 **kwargs 会修改所有的home字段都会修改成0
models.Tb1.objects.filter(name='root').update(home='0')
obj = models.Tb1.objects.get(id=1)
obj.c1 = '111'
obj.save()
方法四:
obj = User.objects.get(id=16)
print(obj)
obj.c1 = '111' #c1 可以重写为obj的字段
obj.save()
数据的查询
方法一:
user=User.objects.get(id=1) # 获取单条数据,不存在则报错(不建议)
#报错信息:User matching query does not exist.
方法二:
# 查询多个结果,有多少返回多少,不存在返回None 获取的数据是QuerySet 需要序列化
user = User.objects.all()
方法三:
#获取指定条件的数据获取的数据是QuerySet 需要序列化
user = User.objects.filter(name='田七')
#<QuerySet [<User: 田七>, <User: 田七>]>
方法四:
models.tb.objects.all().first() #获取全部数据的第1条数据
方法五:
user=User.objects.filter(name='田七', class_room_id=1) # 2个参数,获取指定条件的数据
#<QuerySet [<User: 田七>]>
方法六:
dic = {'name':'seven','password':'123'}
models.tb.objects.filter(**dic) #参数可以是字典形式,获取指定条件的数据
方法七:
dic = {'name':'田七', 'class_room_id':1}
user = User.objects.filter(**dic) # 参数可以是字典形式,获取指定条件的数据
#<QuerySet [<User: 田七>]>
正向查找
# from . import models
print(models.User.objects.get(name='111').class_room.classroom) # 查找学生111所在的班级
# 2001B
print(models.User.objects.filter(class_room=1)) # 查询class_room为1班级所有学生
#<QuerySet [<User: 猪悟能>, <User: 沙僧>, <User: 李四>
反向查找
ClassRoom.user_set.all() 表名_set.all()
# 查询1910E班级所有学生
print(models.ClassRoom.objects.get(classroom='1910E').user_set.all())
#<QuerySet [<User: 猪悟能>, <User: 李四>, <User: 李四>, <User: 田七>]>
2、进阶操作(了不起的双下划线)
其他不常用的操作看:https://www.cnblogs.com/wupeiqi/articles/5246483.html
利用双下划线将字段和对应的操作连接起来
获取个数
models.Tb1.objects.filter(name='田七').count() # 2
比较查询
gt 大于
gte 大于等于
lt 小于
lte 小于等于
exclude 不等于
#字段名__gt 比如:age__gt
#字段名__lt 比如:age__lt
models.User.objects.filter(id__gt=1) # 获取id大于1的值
models.User1.objects.filter(id__gte=1) # 获取id大于等于1的值
models.User.objects.filter(id__lt=10) # 获取id小于10的值
models.User.objects.filter(id__lte=10) # 获取id小于10的值
models.User.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
#<QuerySet [<User: 猪悟能>, <User: 猪悟能>, <User: 沙僧>, <User: 李四>
范围查询 :
in 在范围内
#字段名__in 比如:age__in
models.User.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
models.User.objects.exclude(id__in=[11, 22, 33]) # not in 不在
#<QuerySet [<User: root>]>
range 相当于between...and...
#字段名__rang 比如:age__rang
models.User.objects.filter(id__range=[10,12]) #查询范围为10-12的id
#<QuerySet [<User: 田七>, <User: root>, <User: root>]>
空查询
isnull 是否为空
#字段名__isnull 比如:role__isnull
prin(models.User.objects.filter(role__isnull=Flast)) #输出role字段所有不为空的数据
print(models.User.objects.filter(role__isnull=True)) #输出role字段所有为空的数据
#<QuerySet [<User: 猪悟能>, <User: 沙僧>, <User: 李四>
模糊查询
contains 是否包含
#字段名__contains 比如:name__contains
models.User.objects.filter(name__contains='r') #查询结果包含‘r’的
startswith,endswith 以指定值开头或结尾
istartswith iendswith 以指定值开头或结尾
#字段名__startswith 比如:name__startswith
#字段名__endswith 比如:name__endswith
models.User.objects.filter(name__startswith='李') #查询结果以‘李’开头的数据
#<QuerySet [<User: 李四>, <User: 李四>, <User: 李四>, <User: 李四>]>
models.User.objects.filter(name__endswith='能') #查询结果以‘能’结尾的数据
#<QuerySet [<User: 猪悟能>, <User: 猪悟能>]>
日期查询
year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。
User.objects.filter(pub_date__year=2005)
user.objects.filter(pub_date__year__gte=2005)
regex正则匹配,iregex 不区分大小写
Entry.objects.get(title__regex=r'^(An?|The) +')
Entry.objects.get(title__iregex=r'^(an?|the) +')
聚合函数
使用aggregate()过滤器调用聚合函数。聚合函数包括:Avg 平均,Count 数量,Max 最大,Min 最小,Sum 求和
from django.db.models import Sum,Avg,Count,Max,Min #导包
user = models.User.objects.aggregate(Sum('age')) #求age的总和
#{'age__sum': 279}
F对象和Q对象
比较两个字段对象之间的关系用F对象。(F对象可以进行运算)
from django.db.models import F,Q
user = User.objects.filter(age__gte=F('age')) #查询年龄等于年龄的对象
#可以搭配+ - * /运算符
user=User.objects.update(age=F('age') + 2) #会把数据库中的age字段每个都加2
与逻辑运算符连用使用Q对象。 或( | ) 与( & ) 非( ~ )
from django.db.models import F,Q
user = User.objects.filter(Q(age=12) | Q(name='root')) #查找age为12的数据或name为root的数据
#<QuerySet [<User: root>, <User: root>, <User: root>, <User: root>]>
排序
使用order_by对结果进行排序
user=User.objects.all().order_by('age') #按年龄的升序排列
user=User.objects.all().order_by('-age') #按年龄的降序排列
连表操作(关联查询)
利用双下划线和 _set 将表之间的操作连接起来
- 一对一操作
user = models.User.objects.filter(id=2).first() #查询user表中id为2的数据
#查询id为2的数据的各种字段值
print(user.name)
print(user.age)
print(user.home)
print(user.role)
print(user.class_room_id)
#查询id为2的数据的name age字段值
user = models.User.objects.filter(id=2).values('name', 'age').first()
print(user)
print(user.keys())
print(user.values())
#{'name': '猪悟能', 'age': 17}
#dict_keys(['name', 'age'])
#dict_values(['猪悟能', 17])
-
一对多操作
- 类似一对一
- 1、搜索条件使用 __ 连接 (适用于一表向多表查询数据)
#查询classRoom表id=1的user学生 classInfo=ClassRoom.objects.get(id=1) #使用模型类名称_set users=classInfo.user_set.all() #查询班级表对应的所有学生 数据一般会有很多 搭配序列化
- 2、获取值时使用 . 连接 (适用于多表向一表查询数据)
#根据查询user表的数据.外键名.要查询的外键表里面的字段 user=models.User.objects.filter(id=2).first() data=user.class_room.classroom #查询id为2的学生在哪个班级 print(data) #得出数据 2001B
- 还有一种是在建立模型类的时候使用related_name来指定变量名。
# model.py hbook= model.ForeignKey(HeroInfo,on_delete=model.CACADE,null=Ture,related_name='heros')
-
多对多操作
- 1、建多对多表
#model.py class Student(models.Model): name = models.CharField(max_length=32) # 老师类 class Teacher(models.Model): name = models.CharField(max_length=32) ##让django帮助建立多对多关系表 stu = models.ManyToManyField(to='Student',related_name='teacher')
-
2、数据的增删改查
-
多对多数据添加使用 add
-
多对多数据删除使用 remove
-
多对多数据修改使用 模型类名称__set
-
多对多数据获取使用 模型类名称__set
user = models.ClassRoom.objects.get(classroom='2001B') #查询班级为2001B的班级 user_info_objs = models.ClassRoom.objects.all() #查询所有班级 # 添加数据 #group_obj.user_info.add(user_info_obj) #group_obj.user_info.add(*user_info_objs) # 删除数据 #group_obj.user_info.remove(user_info_obj) #group_obj.user_info.remove(*user_info_objs) # 获取数据 #print user_info_obj.usergroup_set.all() #print user_info_obj.usergroup_set.all().filter(caption='CEO') #print user_info_obj.usergroup_set.all().filter(caption='DBA')
views.py
class ManyToManyTest(APIView): def get(self, request): # 方法一:在建立manytomany的models里查数据 # teacherobj = models.Teacher.objects.get(id=2) # data = teacherobj.stu.all() # data_list = [] # for i in data: # data_dic={ # "student_name":i.name, # "teacher_name":teacherobj.name # } # data_list.append(data_dic) # return Response(data_list) # 方法二:在未建立manytomany的models里查数据 studentobj = models.Student.objects.get(id=2) data = studentobj.teacher_set.all() data_list = [] for i in data: data_dic = { "student_name": studentobj.name, "teacher_name": i.name } data_list.append(data_dic) return Response(data_list) def post(self, request): # 方法一:在建立manytomany的models里添加数据,(一条,一个对象) # teacherobj = models.Teacher.objects.filter(id=1).first() # studentobj = models.Student.objects.filter(id=2).first() # teacherobj.stu.add(studentobj) # return Response({ # "status": 200 # }) #方法二:在未建立manytomany的models里添加数据,(一条,一个对象) teacherobj = models.Teacher.objects.all() studentobj = models.Student.objects.filter(id=2).first() studentobj.teacher_set.set(teacherobj) return Response({ "status": 200 }) def put(self, request): # 方法一:在建立manytomany的models里修改数据,参数只能是可迭代对象 teacherobj = models.Teacher.objects.filter(id=3).first() studentobj = models.Student.objects.filter(id=2) teacherobj.stu.set(studentobj) return Response({ "status": 200 }) #方法二:在未建立manytomany的models里修改数据,参数只能是可迭代对象 # teacherobj = models.Teacher.objects.all() # studentobj = models.Student.objects.filter(id=2).first() # studentobj.teacher_set.set(teacherobj) # return Response({ # "status": 200 # }) def delete(self, request): # 方法一:在建立manytomany的models里删除数据,(一条,一个对象) # teacherobj = models.Teacher.objects.filter(id=1).first() # studentobj = models.Student.objects.filter(id=2).first() # teacherobj.stu.remove(studentobj) # return Response({ # "status": 200 # }) #方法二:在未建立manytomany的models里删除数据,(多条,可迭代对象) teacherobj = models.Teacher.objects.all() studentobj = models.Student.objects.filter(id=2).first() studentobj.teacher_set.remove(*teacherobj) return Response({ "status": 200 })
多对多序列化
使用序列化器来进行查询展示的时候
在多对多的模型类中,直接继承modelserializer,指定depth即可(第一种方法)、
在未存在多对多的模型类里,继承seriizer,模型类_set指定一个序列化器(第二种方法)
- 第一种方法
from rest_framework import serializers from .models import * class UserSerializers(serializers.ModelSerializer): class Meta: model = User fields = "__all__" # fields=('name','age','role') #序列化时显示那些字典 depth = 1 # 外键序列化
- 第二种
class UserSerializers(serializers.ModelSerializer): class Meta: model = User fields = "__all__" # fields=('name','age','role') #序列化时显示那些字典 # depth = 1 # 外键序列化 class RoleSer(serializers.Serializer): # 字段名,必须是模型可以引用到的变量 # User(),Role 才能作为字段名,如果是集合 需要many=True user_set = UserSerializers(many=True) # 添加显示学生字段 class Meta: model = Role fields = "__all__"