使用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根据时间生成mongodb的ObjectId的方法
Mar 13 Python
Python socket编程实例详解
May 27 Python
Python减少循环层次和缩进的技巧分析
Mar 15 Python
Python使用cookielib模块操作cookie的实例教程
Jul 12 Python
Python Web程序部署到Ubuntu服务器上的方法
Feb 22 Python
django使用LDAP验证的方法示例
Dec 10 Python
Python从单元素字典中获取key和value的实例
Dec 31 Python
pandas进行时间数据的转换和计算时间差并提取年月日
Jul 06 Python
python同步两个文件夹下的内容
Aug 29 Python
Python读取分割压缩TXT文本文件实例
Feb 14 Python
pycharm如何实现跨目录调用文件
Feb 28 Python
Python中的流程控制详解
Feb 18 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
桌面中心(一)创建数据库
2006/10/09 PHP
PHP错误Cannot use object of type stdClass as array in错误的解决办法
2014/06/12 PHP
JS继承 笔记
2011/07/13 Javascript
jquery实现图片翻页效果
2013/12/23 Javascript
js实现同一页面可多次调用的图片幻灯切换效果
2015/02/28 Javascript
JS基于cookie实现来宾统计记录访客信息的方法
2015/08/04 Javascript
JavaScript基于扩展String实现替换字符串中index处字符的方法
2017/06/13 Javascript
JavaScript创建对象的七种方式(推荐)
2017/06/26 Javascript
基于Three.js实现360度全景图片
2018/12/30 Javascript
js模拟实现百度搜索
2020/06/28 Javascript
js实现全选和全不选功能
2020/07/28 Javascript
Python中使用摄像头实现简单的延时摄影技术
2015/03/27 Python
Python实现通讯录功能
2018/02/22 Python
Python实现图片尺寸缩放脚本
2018/03/10 Python
将pandas.dataframe的数据写入到文件中的方法
2018/12/07 Python
Python使用pdb调试代码的技巧
2020/05/03 Python
CSS 说明横向进度条最后显示文字的实现代码
2020/11/10 HTML / CSS
基于HTML5+CSS3实现简单的时钟效果
2017/09/11 HTML / CSS
悦木之源美国官网:Origins美国
2016/08/01 全球购物
日本非常有名的内衣丝袜品牌:GUNZE
2017/01/06 全球购物
泰国的头号网上婴儿用品店:Motherhood.co.th
2019/04/09 全球购物
C#如何进行LDAP用户校验
2012/11/21 面试题
毕业研究生的自我鉴定
2013/11/30 职场文书
高校辅导员推荐信范文
2013/12/25 职场文书
服装设计专业自荐书范文
2013/12/30 职场文书
法律进学校实施方案
2014/03/15 职场文书
应届毕业生求职信
2014/05/26 职场文书
创建绿色社区汇报材料
2014/08/22 职场文书
工作检讨书怎么写
2014/10/10 职场文书
单位个人查摆问题及整改措施
2014/10/28 职场文书
2015年超市工作总结
2015/04/09 职场文书
红歌会主持词
2015/07/02 职场文书
爱岗敬业事迹材料
2019/06/20 职场文书
创业计划书之美甲店
2019/09/20 职场文书
golang内置函数len的小技巧
2021/07/25 Golang
CSS使用Flex和Grid布局实现3D骰子
2022/08/05 HTML / CSS