Django多层嵌套ManyToMany字段ORM操作详解


Posted in Python onMay 19, 2020

在用django写项目时,遇到了许多场景,关于ORM操作获取数据的,但是不好描述出来,百度搜索关键词都不知道该怎么搜,导致一个人鼓捣了好久。这里细化下问题,还原场景,记录踩下的坑

首先先列举model,我举些生活中的例子,更方便理解问题

# 习题
class Problem(models.Model):
  desc = models.CharField()
  answer = models.TextField()
  is_pass = models.BooleanField(default=False, verbose_name="是否通过")

# 章节
class Chapter(models.Model):
  _id = models.IntegerField(verbose_name="编号")
  title = models.CharField()
  problem = models.ManyToManyField(Problem)
  pass_rate = models.IntegerField(verbose_name="通关率")

# 书籍  
class Book(models.Model):
  title = models.CharField()
  desc = models.TextField()
  chapter = models.ManyToManyField(Chapter,verbose_name="章节")
  speed = models.IntegerField(verbose_name="学习进度", default=0)

假设是一本数学书,有5个章节,每个章节里有数量不等的习题,

即book与chapter是多对多,chapter与problem也是多对多

场景一: 书籍下的所有习题

# 按我的理解是取问题非空的章节数
# 类似于问爷爷有几个孙子,没办法跨辈,就按一个孙子对应一个爸爸来取(有重复)
book.chapter.filter(problem___id__isnull=False).count()

场景二:书籍下所有通过的习题

book.chapter.filter(problem__is_pass=True).count()

场景三: 判断某个问题是否在这本书里

def problem_in_ladder(book, problem):
    for i in book.chapter.all():
      if problem in i.problem.all():
        return True
    return False

尽可能的减少view中对models的取值操作,所以把上面几个场景方法写在models类中

最终的models

# 习题
class Problem(models.Model):
  desc = models.CharField()
  answer = models.TextField()
  is_pass = models.BooleanField(default=False, verbose_name="是否通过")

# 章节
class Chapter(models.Model):
  _id = models.IntegerField(verbose_name="编号")
  title = models.CharField()
  problem = models.ManyToManyField(Problem)
  pass_rate = models.IntegerField(verbose_name="通关率")
 
  @property
  def items(self):
    return self.problem.count()

  @property
  def pass_problem(self):
    return self.problem.filter(is_pass=True).count()
  
# 书籍  
class Book(models.Model):
  title = models.CharField()
  desc = models.TextField()
  chapter = models.ManyToManyField(Chapter,verbose_name="章节")
  speed = models.IntegerField(verbose_name="学习进度", default=0)
  
  @property
  def chapters(self):
    return self.chapter.count()

  @property
  def pass_count(self):
    return self.chapter.filter(problem__is_pass=True).count()

  @property
  def items(self):
    return self.chapter.filter(problem___id__isnull=False).count()

补充知识:django中当model设置了ordering后,使用distinct()和annotate()问题记录

model类如下,我在class Meta中设置了ordering = ['-date_create'],即模型对象返回的记录结果集是按照这个字段排序的。

class SystemUserPushHistory(models.Model):
 
  id = models.UUIDField(default=uuid.uuid4, primary_key=True)
  host_name = models.CharField(max_length=128, null=False)
  system_username = models.CharField(max_length=128, null=False)
  method = models.CharField(max_length=32, null=False)
  is_success = models.BooleanField(default=False)
  date_create = models.DateTimeField(auto_now_add=True, editable=False)
  message = models.CharField(max_length=4096, null=True)
 
  class Meta:
    db_table = "assets_systemuser_push_history"
    ordering = ['-date_create']
 
  def __str__(self):
    ret = self.system_username + " => " + self.host_name
    return ret

当业务有需求如对host_name进行分组显示,在代码中用到了annotate,如下。

>>> from django.db.models import Count 
>>> from assets.models import SystemUserPushHistory
>>> p = SystemUserPushHistory.objects.values("host_name").annotate(dcount=Count(1))
>>> p
<QuerySet [{'host_name': '点2', 'dcount': 1}, {'host_name': '点3', 'dcount': 2}, {'host_name': '点2', 'dcount': 1}, {'host_name': '点3', 'dcount': 1}]>
>>> print(p.query)
SELECT `assets_systemuser_push_history`.`host_name`, COUNT(1) AS `dcount` FROM `assets_systemuser_push_history` GROUP BY `assets_systemuser_push_history`.`host_name`, `assets_systemuser_push_history`.`date_create` ORDER BY `assets_systemuser_push_history`.`date_create` DESC

可以看到,所得到的结果并不像我们预期的一样,之后把执行的sql输出出来可以看到在group by的时候是对host_name和date_create进行分组,原因就是因为我们在model类中设置了ordering,去掉之后代码运行正常。

使用distinct和上面的情况类似,就不列出来了。

以上这篇Django多层嵌套ManyToMany字段ORM操作详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python用户推荐系统曼哈顿算法实现完整代码
Dec 01 Python
Pandas中把dataframe转成array的方法
Apr 13 Python
Python高级特性切片(Slice)操作详解
Sep 27 Python
Python对切片命名的实现方法
Oct 16 Python
python读取word文档,插入mysql数据库的示例代码
Nov 07 Python
Python求两个圆的交点坐标或三个圆的交点坐标方法
Nov 07 Python
python分数表示方式和写法
Jun 26 Python
Python如何基于smtplib发不同格式的邮件
Dec 30 Python
OpenCV哈里斯(Harris)角点检测的实现
Jan 15 Python
部署Django到阿里云服务器教程示例
Jun 03 Python
python 爬取哔哩哔哩up主信息和投稿视频
Jun 07 Python
Python中使用tkFileDialog实现文件选择、保存和路径选择
May 20 Python
django ORM之values和annotate使用详解
May 19 #Python
基于python实现地址和经纬度转换
May 19 #Python
Python Django form 组件动态从数据库取choices数据实例
May 19 #Python
Django自关联实现多级联动查询实例
May 19 #Python
Python的Django框架实现数据库查询(不返回QuerySet的方法)
May 19 #Python
django 数据库返回queryset实现封装为字典
May 19 #Python
使用PyQt的QLabel组件实现选定目标框功能的方法示例
May 19 #Python
You might like
CodeIgniter图像处理类的深入解析
2013/06/17 PHP
php设计模式之单例、多例设计模式的应用分析
2013/06/30 PHP
PHP的password_hash()使用实例
2014/03/17 PHP
php输出指定时间以前时间格式的方法
2015/03/21 PHP
PHP生成各种常见验证码和Ajax验证过程
2016/01/10 PHP
PHP5.4起内置web服务器使用方法
2016/08/09 PHP
php使用scandir()函数扫描指定目录下所有文件示例
2019/06/08 PHP
jQuery 版本的文本输入框检查器Input Check
2009/07/09 Javascript
IE 条件注释详解总结(附实例代码)
2009/08/29 Javascript
javascript+iframe 实现无刷新载入整页的代码
2010/03/17 Javascript
Jquery为单选框checkbox绑定单击click事件
2012/12/18 Javascript
基于JQuery 选择器使用说明介绍
2013/04/18 Javascript
Javascript 鼠标移动上去小三角形滑块缓慢跟随效果
2013/04/26 Javascript
js数组常见操作及数组与字符串相互转化实例详解
2015/11/10 Javascript
Layui点击图片弹框预览的实现方法
2019/09/16 Javascript
jQuery列表动态增加和删除的实现方法
2020/11/05 jQuery
Python导入oracle数据的方法
2015/07/10 Python
分享一下如何编写高效且优雅的 Python 代码
2017/09/07 Python
python:pandas合并csv文件的方法(图书数据集成)
2018/04/12 Python
Linux下python与C++使用dlib实现人脸检测
2018/06/29 Python
python实现屏保计时器的示例代码
2018/08/08 Python
python3 实现一行输入,空格隔开的示例
2018/11/14 Python
Python编程中类与类的关系详解
2019/08/08 Python
keras使用Sequence类调用大规模数据集进行训练的实现
2020/06/22 Python
keras的三种模型实现与区别说明
2020/07/03 Python
python利用xlsxwriter模块 操作 Excel
2020/10/14 Python
一款利用html5和css3实现的3D立方体旋转效果教程
2016/04/26 HTML / CSS
video下autoplay属性无效的解决方法(添加muted属性)
2020/05/19 HTML / CSS
戴尔美国官方折扣店:Dell Outlet
2018/02/13 全球购物
圣彼得堡鲜花配送:Semicvetic
2020/09/15 全球购物
Perfume’s Club澳大利亚官网:西班牙领先的在线美容店
2021/02/01 全球购物
加拿大探亲邀请信
2014/01/28 职场文书
电子信息专业应届生自荐信
2014/06/04 职场文书
2014年国庆节活动总结
2014/08/26 职场文书
2014城乡环境综合治理工作总结
2014/12/19 职场文书
事业单位财务人员岗位职责
2015/04/14 职场文书