使用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 相关文章推荐
在Django的URLconf中使用命名组的方法
Jul 18 Python
python3音乐播放器简单实现代码
Apr 20 Python
python导入时小括号大作用
Jan 10 Python
Python 迭代器与生成器实例详解
May 18 Python
关于python写入文件自动换行的问题
Jun 23 Python
Python列表常见操作详解(获取,增加,删除,修改,排序等)
Feb 18 Python
使用Python实现跳帧截取视频帧
May 31 Python
基于keras 模型、结构、权重保存的实现
Jan 24 Python
Python生成随机验证码代码实例解析
Jun 09 Python
深入了解Python 方法之类方法 & 静态方法
Aug 17 Python
再也不用花钱买漫画!Python爬取某漫画的脚本及源码
Jun 09 Python
Python 数据结构之十大经典排序算法一文通关
Oct 16 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创建Cookie数组的详解
2013/07/03 PHP
PHP strip_tags()去除HTML、XML以及PHP的标签介绍
2014/02/18 PHP
Javascript与PHP验证用户输入URL地址是否正确
2014/10/09 PHP
3款值得推荐的微信开发开源框架
2014/10/28 PHP
在你的网页中嵌入外部网页的方法
2007/04/02 Javascript
js判断选择时间不能小于当前时间的示例代码
2013/09/24 Javascript
jquery进行数组遍历如何跳出当前的each循环
2014/06/05 Javascript
javascript实现控制浏览器全屏
2015/03/30 Javascript
jQuery中toggle()函数的使用实例
2015/04/17 Javascript
js实现卡片式项目管理界面UI设计效果
2015/12/08 Javascript
AngularJS 过滤器的简单实例
2016/07/27 Javascript
AngularJS应用开发思维之依赖注入3
2016/08/19 Javascript
在JSP中如何实现MD5加密的方法
2016/11/02 Javascript
JavaScript中setTimeout的那些事儿
2016/11/14 Javascript
概述如何实现一个简单的浏览器端js模块加载器
2016/12/07 Javascript
微信小程序云开发(数据库)详解
2019/05/17 Javascript
vue 解决路由只变化参数页面组件不更新问题
2019/11/05 Javascript
js仿京东放大镜效果
2020/08/09 Javascript
js轮播图之旋转木马效果
2020/10/13 Javascript
python实现定时提取实时日志程序
2018/06/22 Python
Python实现九宫格式的朋友圈功能内附“马云”朋友圈
2019/05/07 Python
Python 如何优雅的将数字转化为时间格式的方法
2019/09/26 Python
解决Python列表字符不区分大小写的问题
2019/12/19 Python
python opencv实现图片缺陷检测(讲解直方图以及相关系数对比法)
2020/04/07 Python
在Ubuntu 20.04中安装Pycharm 2020.1的图文教程
2020/04/30 Python
python+excel接口自动化获取token并作为请求参数进行传参操作
2020/11/10 Python
CSS3制作圆形滚动进度条动画的示例
2020/11/05 HTML / CSS
里程积分管理买卖交换平台:Points.com
2017/01/13 全球购物
越南母婴用品购物网站:Kids Plaza
2020/04/09 全球购物
党性教育心得体会
2014/09/03 职场文书
分居协议书范本
2014/11/03 职场文书
2015年社区中秋节活动总结
2015/03/23 职场文书
MySQL锁机制
2021/04/05 MySQL
Redis 配置文件重要属性的具体使用
2021/05/20 Redis
php 文件上传至OSS及删除远程阿里云OSS文件
2021/07/04 PHP
Rust 连接 PostgreSQL 数据库的详细过程
2022/01/22 PostgreSQL