ORM ,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法
Django修改表数据的两种方法:
# 第一种 <class 'django.db.models.query.QuerySet'>
info = User.objects.filter(id=request.user_id)
info.update(account=account)
# 第二种 <class 'user.models.User'>
info2 = User.objects.filter(id=request.user_id).first()
info2.name = name
info2.save()
ORM 查询操作
.get() 得到一条数据,不存在则报错
.filter() 过滤查询 得到一个列表,不存在为空列表
.first() 从列表中取出第一条数据,是一个对象,不是列表
.filter().exclude() 排除当前表中某条数据
示例:
other_settings = ExamSetting.objects.filter(plan=plan).exclude(id=instance.id)
class Category(models.Model):
cate_name = models.CharField(max_length=50, verbose_name='类别名')
class Goods(models.Model):
cate = models.ForeignKey(Category, related_name='goods', on_delete=models.CASCADE, verbose_name='用户')
两表联查:1. 通过主表id 查询对应的 子表的数据:(反向查询)
cat=Category.objects.get(id=cate_id)
------ 获取主表id对应的对象
goods_data = cat.goods_set.all()
------ 对象.模型类小写_set.all()
------ 获取子表中关联主表的对象的所有数据
2. 模型类添加属性 related_name
cat=Category.objects.get(id=cate_id)
------ 获取主表id对应的对象
goods_data = cat.goods.all()
------ 对象.related绑定对象.all()
related_name用于反向查询 cat.goods.all()
不定义的话 就是cat.goods_set.all()
3. cate对象 cate_id对象的id (正向查询)
goods_queryset = Goods.objects.filter(cate_id=cate_id)
----- 子表模型类.objects.filter(外键_id=主表的id)
查询ManyToManyField 多对多
class StudentGroup(models.Model):
# 示例:TYPE
TYPE = [
('news', '资讯'),
('notice', '公告')
]
class Meta:
db_table = 'group'
category = models.CharField(max_length=10, choices=TYPE, verbose_name='类型')
name = models.CharField(max_length=20, verbose_name='名称', unique=True, db_index=True)
parent = models.ForeignKey(to='self', null=True, blank=True, on_delete=models.CASCADE, verbose_name='父级')
students = models.ManyToManyField(to='Student', null=True, blank=True, verbose_name='学员')
plans = models.ManyToManyField(to='Plan', null=True, blank=True, verbose_name='学习计划')
note = models.CharField(max_length=120, null=True, blank=True, verbose_name='备注')
link = models.CharField(max_length=10, null=True, blank=True, verbose_name='联系人')
email = models.EmailField(max_length=100, null=True, blank=True, verbose_name='联系人邮箱')
phone = models.CharField(max_length=20, null=True, blank=True, verbose_name='联系方式')
create_user = models.ForeignKey(to='User', null=True, blank=True, related_name='user_create_uc_set',
on_delete=models.PROTECT, verbose_name='创建人')
write_user = models.ForeignKey(to='User', null=True, blank=True, related_name='user_write_uc_set',
on_delete=models.PROTECT, verbose_name='修改人')
def __str__(self) -> str:
return self.name
获取学生群组中包含该学生的所有群组
student_groups = StudentGroup.objects.filter(students__id=student_id)
从上面的学生群组中获取关联的学习计划的 IDs
plan_ids = student_groups.values_list('plans', flat=True).distinct()
获取 Plan 对象
related_plans = Plan.objects.filter(id__in=plan_ids)
匹配查询符合对象id或对象列表的所有数据
planinfo_list = PlanInfo.objects.filter(plan_id__in=plan_ids)
planinfo_list = PlanInfo.objects.filter(plan__in=related_plans)
ORM语法补充
students = Student.objects.filter(pk__in=students_ids)
# pk 表中唯一标识,主键(Primary Key)的缩写
在PassagePlanInfo表中查询所有匹配学生id和匹配planinfos列表中对象的查询结果
在matching_records 查询结果中使用filter().exists() 结果返回为真,即return
planinfos=PlanInfo.objects.filter(plan=plan)
matching_records = PassagePlanInfo.objects.filter(
student_id=student_id,
plan_info__in=planinfos
)
if matching_records.filter(done=False).exists():
return JsonResponse({'code': 400, 'msg': '有课程尚未学完,暂不能考试'})
检查是否存在DiplomaMyInfo关联记录
if DiplomaMyInfo.objects.filter(diploma=instance).exists():
return Response({"detail": "不能删除,存在关联记录。"},status=status.HTTP_400_BAD_REQUEST)
modelviewset重新父类方法时调用父类方法
response = super().list(request, *args, **kwargs)
排除多对多关系中 active 字段为 True 的记录的
queryset = queryset.exclude(students__active=True)
排除当前表中 active 字段为 True 的记录的
queryset = self.filter_queryset(self.get_queryset()).filter(active=False)
any() 内置的 Python 函数,用于检查可迭代对象(如列表、元组、集合等)中是否至少有一个元素为 True 或等效于 True。如果至少有一个元素为真,则 any() 返回 True,否则返回 False。
lis = [None, None, 0]
flag = any(i for i in lis)
1.获取StudentGroup表中ManyToManyField字段的所有符合数据
2.获取相关所有计划, .values_list('')方法中可以回显id,或者用name 什么字段都行
student_groups = StudentGroup.objects.filter(students=student_id)
plan_ids = Plan.objects.filter(studentgroup__in=student_groups).values_list('id', flat=True)
Python方法补充
sum方法,满足条件,计数加1
sum(1 for item in subject_res if list(item.values())[0])
重组表字段信息 多条数据用for
class ContentApi(APIView):
def get(self, request):
new_info = []
content_info = Content.objects.all() # 获取子表查询结果集
for i in content_info: # 循环出每条数据
a = { # 通过class对象调用字段的方法 重组一个新列表
'intro': i.intro, # i是每一条数据的对象,i.intro就是对应这个对象的这条数据
'cover': i.cover,