使用Django实现把两个模型类的数据聚合在一起


Posted in Python onMarch 28, 2020

Django中想要把模型类聚合得到想要的数据可以用F对象。

比如有模型类A和B,A和B之间有外键关联在一起,A是子表,B是父表(反过来没试过。。因为大部分数据都是用子表的,我想是可以的),那么可以这样查:

A.objects.filter(userid=3,bookid=F(bid))

其中userid,bookid是模型类A的字段,bid是模型类B的字段。

这样操作的结果就是可以查询到userid为3且模型类A字段bookid等于模型类B字段bid的集合数据了。

F对象是可以比较两个关联模型类的字段数据的。

我看到网上有说F对象可以这样用F('b__id') ==>F('模型类名小写__字段名'),此处是双下划线。

但是我用Django2.0时会报错。。真是搞不懂,后来我直接使用字段名居然可以,醉了。

反正都可以试试吧

A.objects.filter(userid=3,bookid=F(bid))

A.objects.filter(userid=3,bookid=F('b__bid'))

补充知识:Django Admin页面显示父表,编辑子表

默认情况下,ModelAdmin只允许您管理模型“本身”字段,而不是相关模型.以下方法将实现,在应用类的列表管理显示页面,显示父表的字段;在编辑页面,父表对子表进行编辑.

models.py如下

class Level(models.Model):
 # l_num = models.IntegerField(default=0, verbose_name='序号')
 name = models.CharField(max_length=20)
 is_delete = models.BooleanField(default=False)
 
 def __str__(self):
  return self.name

class Grades(models.Model):
 name = models.CharField(max_length=20, verbose_name='班级')
 # 外键,这里关联模型Level与模型名称一样,不是全小写。
 level = models.ForeignKey('Level', on_delete=models.DO_NOTHING)
 is_delete = models.BooleanField(default=False)
 
 def __str__(self):
  return '%s%s' % (self.level, self.name)

class Students(models.Model):
 name = models.CharField(max_length=20, db_index=True, verbose_name='姓名')
 age = models.IntegerField(verbose_name='年龄')

 # 需要先提供一个二维的二元元组,第一个元素表示存在数据库内真实的值,第二个表示页面上显示的具体内容
 SEX_CHOICE = (
  ('男', '男'),
  ('女', '女'),
 )
 sex = models.CharField(max_length=10, choices=SEX_CHOICE, verbose_name='性别', default='男')
 grade = models.ForeignKey('Grades', on_delete=models.DO_NOTHING, verbose_name="班级")
 img_student = models.ImageField(upload_to='img_student', default='img_student/default.png', verbose_name='头像')
 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
 last_update_time = models.DateTimeField(auto_now=True, verbose_name='上次更新时间')
 is_delete = models.BooleanField(default=False)
 
 def __str__(self):
  return self.name

在admin.py代码如下:

@admin.register(Students)
class StudentsAdmin(admin.ModelAdmin):
 list_display = ('name', 'age', 'sex', 'grade', 'create_time', 'last_update_time', 'is_delete')

做完之后,显示的效果如下:

使用Django实现把两个模型类的数据聚合在一起

在应用类的列表管理显示页面,显示父表的字段

可以让Students,显示父表Grades的父表Level字段

在models.py里的Students类里,写上如下代码:

class Students(models.Model):

# 写一个方法,定义在管理页面上能够显示的外键字段字段
  # grade为Students模型的外检表,level为Grades模型的外检表,那么为Level模型的字段
  def dis_level(self):
   return self.grade.level.name

  # 定义该字段在管理后台显示的名称
  dis_level.short_description = '年级'
  
 # 定义该字段在管理后台显示的名称
 dis_level.short_description = '年级'
 # 方法列是不能排序的,如果需要排序需要为方法指定排序依据。添加的是'模型类字段'
 # 如果是外键需要遵循这样的语法:本表外键字段__(双下划线)外检表字段或外检表的外键字段__最终外键表要显示的字段。
 dis_level.admin_order_field = 'grade__level__name'

在admin.py里,把Students类里的方法,加入到list_display里:

@admin.register(Students)
class StudentsAdmin(admin.ModelAdmin):
 list_display = ('name', 'age', 'sex', 'grade', 'dis_level', 'create_time', 'last_update_time', 'is_delete')

写完之后,显示的结果如下,多了年级,以及点击年级可以进行排序:

使用Django实现把两个模型类的数据聚合在一起

在编辑页面,父表对子表进行编辑.

默认对学生编辑时,无法在编辑页面直接编辑相关联的子表,例如:

models.py代码:

class Students(models.Model):
 name = models.CharField(max_length=20, db_index=True, verbose_name='姓名')
 age = models.IntegerField(verbose_name='年龄')

 # 需要先提供一个二维的二元元组,第一个元素表示存在数据库内真实的值,第二个表示页面上显示的具体内容
 SEX_CHOICE = (
  ('男', '男'),
  ('女', '女'),
 )
 sex = models.CharField(max_length=10, choices=SEX_CHOICE, verbose_name='性别', default='男')
 grade = models.ForeignKey('Grades', on_delete=models.DO_NOTHING, verbose_name="班级")
 img_student = models.ImageField(upload_to='img_student', default='img_student/default.png', verbose_name='头像')
 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
 last_update_time = models.DateTimeField(auto_now=True, verbose_name='上次更新时间')
 is_delete = models.BooleanField(default=False)
 
 def __str__(self):
  return self.name


class Course(models.Model):
 name = models.CharField(max_length=20, verbose_name='课名')
 is_delete = models.BooleanField(default=False)
 
 def __str__(self):
  return self.name


class Score(models.Model):
 s_score = models.IntegerField(default=0, verbose_name='分数')
 s_course = models.ForeignKey('Course', on_delete=models.DO_NOTHING, verbose_name='课程')
 s_student = models.ForeignKey('Students', on_delete=models.DO_NOTHING, verbose_name='学生姓名')
 is_delete = models.BooleanField(default=False)
 
 def __str__(self):
  # 要把s_score转换为字符串,否则会报下面的错误。
  """
   Exception Type:TypeError
   Exception Value:
   __str__ returned non-string (type int)
   :return:
  """
  return '%s%s%s' % (self.s_student, self.s_course, str(self.s_score))

打开学生的编辑页面,是这样子的:

使用Django实现把两个模型类的数据聚合在一起

要给学生添加分数,只能进入Score管理页面,一个个添加,非常麻烦.

使用Django的TabularInline,可以解决这个问题,在父表里对子表进行编辑:

所有代码都在admin.py里写,具体如下:

# 一对多关联表编辑,让父表管理配置页面能同时编辑子表,以下的Score为子表(有外键所在的表)
class ScoreInline(admin.TabularInline):
 # Score 必须是models.py中的模型名称,大小写必须要匹配.这个模型为子表,以便可以被父表编辑
 model = Score
 # 默认显示条目的数量
 # extra = 5
 
class StudentsAdmin(admin.ModelAdmin):
 # Inline把ScoreInline关联进来,让父表管理配置页面能同时编辑子表.
 inlines = [ScoreInline, ]

做完之后,效果如下:

使用Django实现把两个模型类的数据聚合在一起

以上这篇使用Django实现把两个模型类的数据聚合在一起就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现的文件同步服务器实例
Jun 02 Python
在Python的Django框架中调用方法和处理无效变量
Jul 15 Python
python实现网站的模拟登录
Jan 04 Python
Python实现图片滑动式验证识别方法
Nov 09 Python
详解python持久化文件读写
Apr 06 Python
python 求某条线上特定x值或y值的点坐标方法
Jul 09 Python
Python浮点数四舍五入问题的分析与解决方法
Nov 19 Python
python使用ctypes调用扩展模块的实例方法
Jan 28 Python
谈一谈数组拼接tf.concat()和np.concatenate()的区别
Feb 07 Python
解决python 执行sql语句时所传参数含有单引号的问题
Jun 06 Python
Python同时处理多个异常的方法
Jul 28 Python
Python 中 sorted 如何自定义比较逻辑
Feb 02 Python
使用python客户端访问impala的操作方式
Mar 28 #Python
python 安装impala包步骤
Mar 28 #Python
django 链接多个数据库 并使用原生sql实现
Mar 28 #Python
Django多数据库配置及逆向生成model教程
Mar 28 #Python
后端开发使用pycharm的技巧(推荐)
Mar 27 #Python
如何基于python3和Vue实现AES数据加密
Mar 27 #Python
python小程序基于Jupyter实现天气查询的方法
Mar 27 #Python
You might like
领悟php接口中interface存在的意义
2013/06/27 PHP
php中使用session_set_save_handler()函数把session保存到MySQL数据库实例
2014/11/06 PHP
php实现俄罗斯乘法实例
2015/03/07 PHP
PHP实现从远程下载文件的方法
2015/03/12 PHP
PHP中isset与array_key_exists的区别实例分析
2015/06/02 PHP
php微信开发之关键词回复功能
2018/06/13 PHP
Codeigniter里的无刷新上传的实现代码
2019/04/14 PHP
Laravel 实现Controller向blade前台模板赋值的四种方式小结
2019/10/22 PHP
jquery属性过滤选择器使用示例
2013/06/18 Javascript
jQuery实现div浮动层跟随页面滚动效果
2014/02/11 Javascript
浅析javascript中function 的 length 属性
2014/05/27 Javascript
推荐一款jQuery插件模板
2015/01/09 Javascript
深入理解javascript作用域第二篇之词法作用域和动态作用域
2016/07/24 Javascript
JS+CSS实现滚动数字时钟效果
2017/12/25 Javascript
详解vue中点击空白处隐藏div的实现(用指令实现)
2018/04/19 Javascript
浅谈Vue.js路由管理器 Vue Router
2018/08/16 Javascript
在小程序中使用canvas的方法示例
2018/09/17 Javascript
在Bootstrap开发框架中使用dataTable直接录入表格行数据的方法
2018/10/25 Javascript
js实现点赞效果
2020/03/16 Javascript
[01:32]TI奖金增速竟因它再创新高!DOTA2勇士令状不朽珍藏Ⅰ饰品欣赏
2018/05/18 DOTA
[20:39]DOTA2-DPC中国联赛 正赛开幕式 1月18日
2021/03/11 DOTA
探寻python多线程ctrl+c退出问题解决方案
2014/10/23 Python
python通过yield实现数组全排列的方法
2015/03/18 Python
Python处理json字符串转化为字典的简单实现
2016/07/07 Python
Python使用zip合并相邻列表项的方法示例
2018/03/17 Python
python取数作为临时极大值(极小值)的方法
2018/10/15 Python
对django views中 request, response的常用操作详解
2019/07/17 Python
python3.6生成器yield用法实例分析
2019/08/23 Python
python+selenium定时爬取丁香园的新型冠状病毒数据并制作出类似的地图(部署到云服务器)
2020/02/09 Python
HTML5 预加载让页面得以快速呈现
2013/08/13 HTML / CSS
美国马匹用品和马钉购物网站:State Line Tack
2018/08/05 全球购物
雪山饭庄的创业计划书范文
2014/01/18 职场文书
三年大学生活自我鉴定
2014/01/21 职场文书
大学生优秀班干部事迹材料
2014/05/26 职场文书
初中班主任教育随笔
2015/08/15 职场文书
Java基础之线程锁相关知识总结
2021/06/30 Java/Android