使用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基本操作:连接、查询实例
Feb 13 Python
简单介绍Python的轻便web框架Bottle
Apr 08 Python
Python爬虫利用cookie实现模拟登陆实例详解
Jan 12 Python
Python实现运行其他程序的四种方式实例分析
Aug 17 Python
python对excel文档去重及求和的实例
Apr 18 Python
Python3+Appium安装使用教程
Jul 05 Python
Python图像处理模块ndimage用法实例分析
Sep 05 Python
python 多进程并行编程 ProcessPoolExecutor的实现
Oct 11 Python
使用Python实现正态分布、正态分布采样
Nov 20 Python
Python日志syslog使用原理详解
Feb 18 Python
python和php哪个更适合写爬虫
Jun 22 Python
python 将Excel转Word的示例
Mar 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 ADODB使用方法集锦
2008/03/25 PHP
php有道翻译api调用方法实例
2014/12/22 PHP
PHP解耦的三重境界(浅谈服务容器)
2017/03/13 PHP
php 字符串中是否包含指定字符串的多种方法
2018/04/12 PHP
redis+php实现微博(一)注册与登录功能详解
2019/09/23 PHP
JavaScript监测ActiveX控件是否已经安装过的代码
2008/09/02 Javascript
基于mootools插件实现遮罩层新手引导
2012/05/24 Javascript
jQuery中对节点进行操作的相关介绍
2013/04/16 Javascript
ie7+背景透明文字不透明超级简单的实现方法
2014/01/17 Javascript
js取模(求余数)隔行变色
2014/05/15 Javascript
JavaScript避免内存泄露及内存管理技巧
2014/09/05 Javascript
node.js中的fs.fstat方法使用说明
2014/12/15 Javascript
node.js调用C++开发的模块实例
2015/07/03 Javascript
简单纯js实现点击切换TAB标签实例
2015/08/23 Javascript
Javascript获取统一管理的提示语(message)
2016/02/03 Javascript
论JavaScript模块化编程
2016/03/07 Javascript
JavaScript实现in-place思想的快速排序方法
2016/08/07 Javascript
js实现拖拽上传图片功能
2017/08/01 Javascript
判断div滑动到底部的scroll实例代码
2017/11/15 Javascript
小程序最新获取用户昵称和头像的方法总结
2019/09/23 Javascript
详解利用eventemitter2实现Vue组件通信
2019/11/04 Javascript
微信小程序事件流原理解析
2019/11/27 Javascript
keep-alive不能缓存多层级路由菜单问题解决
2020/03/10 Javascript
python3实现基于用户的协同过滤
2018/05/31 Python
python使用ddt过程中遇到的问题及解决方案【推荐】
2018/10/29 Python
详解python中list的使用
2019/03/15 Python
jupyternotebook 撤销删除的操作方式
2020/04/17 Python
Keras设置以及获取权重的实现
2020/06/19 Python
html5+css如何实现中间大两头小的轮播效果
2018/12/06 HTML / CSS
美国演唱会和体育门票购买网站:Ticketnetwork
2018/10/19 全球购物
公务员的自我鉴定
2013/10/26 职场文书
舞蹈比赛获奖感言
2014/02/04 职场文书
护士个人年度总结范文
2015/02/13 职场文书
邹越演讲观后感
2015/06/15 职场文书
学会掌握自己命运的十条黄金法则:
2019/08/08 职场文书
分享一个vue实现的记事本功能案例
2022/04/11 Vue.js