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

 更新时间:2020年03月28日 09:49:47   作者:肾虚少年  
这篇文章主要介绍了使用Django实现把两个模型类的数据聚合在一起,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

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')

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

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

可以让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')

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

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

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

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))

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

要给学生添加分数,只能进入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实现把两个模型类的数据聚合在一起就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 探索Python元类的魅力:灵活定制类的创建过程

    探索Python元类的魅力:灵活定制类的创建过程

    在Python编程中,元类(Metaclass)是一项高级特性,它允许我们在定义类的时候动态地控制类的创建过程。元类提供了一种强大的机制,可以对类进行定制化,扩展其功能,并在类的实例化过程中执行额外的操作,本文将深入解析
    2023-10-10
  • 解决tensorflow训练时内存持续增加并占满的问题

    解决tensorflow训练时内存持续增加并占满的问题

    今天小编就为大家分享一篇解决tensorflow训练时内存持续增加并占满的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01
  • python中numpy.zeros(np.zeros)的使用方法

    python中numpy.zeros(np.zeros)的使用方法

    下面小编就为大家带来一篇python中numpy.zeros(np.zeros)的使用方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • 解决pycharm回车之后不能换行或不能缩进的问题

    解决pycharm回车之后不能换行或不能缩进的问题

    今天小编就为大家分享一篇解决pycharm回车之后不能换行或不能缩进的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-01-01
  • Pycharm配置Anaconda环境的详细图文教程

    Pycharm配置Anaconda环境的详细图文教程

    PyCharm是一款很好用很流行的python编辑器,Anaconda通过管理工具包、开发环境、Python版本,大大简化了你的工作流程,下面这篇文章主要给大家介绍了关于Windows系统下Pycharm配置Anaconda环境的相关资料,需要的朋友可以参考下
    2023-02-02
  • Python如何遍历numpy数组

    Python如何遍历numpy数组

    这篇文章主要介绍了Python如何遍历numpy数组问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 由Python运算π的值深入Python中科学计算的实现

    由Python运算π的值深入Python中科学计算的实现

    这篇文章主要介绍了由Python运算π的值深入Python中科学计算的实现,由简单的计算发散出各种算法的讲解,需要的朋友可以参考下
    2015-04-04
  • 基于OpenCV实现视频循环播放

    基于OpenCV实现视频循环播放

    这篇文章主要为大家介绍了如何利用OpenCV实现视频的循环播放,本文为大家提供了两种方式,一个是利用Python语言实现,一个是利用C++语言实现,需要的可以参考一下
    2022-02-02
  • PyGame贪吃蛇的实现代码示例

    PyGame贪吃蛇的实现代码示例

    贪吃蛇是款经典游戏,本文将带你一步步用python语言实现一个贪吃蛇小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • Python 2.7中文显示与处理方法

    Python 2.7中文显示与处理方法

    今天小编就为大家分享一篇Python 2.7中文显示与处理方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07

最新评论