【问题标题】:Add to m2m field on seperate model添加到单独模型上的 m2m 字段
【发布时间】:2021-03-05 23:02:13
【问题描述】:

问题:

我在 3 个独立的应用中有 3 个模型

学校
学生
教室

class School(models.Model): 
    Name = models.CharField(max_length=100)
    Students = models.ManyToManyField(Student) 


class Classroom(models.Model): 
    School = models.ForeignKey(School, on_delete=models.CASCADE)
    Students = models.ManyToManyField(Student) 

我想要什么:

保存新教室后,该教室实例中的学生会自动添加到学校模型的学生多对多字段中。

然后在学校页面模板中,我想按学生添加到学校模型的日期顺序显示学生,我认为这部分需要一个单独的直通模型,但我无法理解。

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

    保存新教室后,该教室实例中的学生会自动添加到学校模型的学生多对多字段中。

    没有这样的行为,我可以建议:

    删除School.Students,那么任何时候你需要特定学校的学生,你都可以这样做

    Students.objects.filter(classroom__School__Name="Hogwarts")
    

    如果您想保留两者(无论出于何种原因),您可以创建自定义函数,将项目添加到两者中。或者您可以创建自定义管理器来修改默认行为。

    然后在学校页面模板中,我想按学生添加到学校模型的日期顺序显示学生 - 我认为这部分需要一个单独的直通模型,但我无法理解它。

    您是对的,如果您想将任何字段添加到多对多,您需要定义您的自定义模型。然后您可以使用through 选项从中创建多对多。

    【讨论】:

    • 其实有这样的行为,自定义保存方法就可以了,但是没必要,因为这是复制数据,更多信息见我的回答
    • 多对多更改不会通过自定义保存方法,仅适用于普通模型字段。无论如何,您当然可以以某种方式自定义它们,但您不应该在没有很大原因的情况下修改默认行为:)
    • Mb,我认为应该做一个信号
    • @GTEE 不客气 :) 记得点赞并接受您认为有帮助的答案。
    【解决方案2】:

    首先,我想坚持一些 pep8 修复

    class School(models.Model): 
        name = models.CharField(max_length=100)
        students = models.ManyToManyField(Student) 
    
    class Classroom(models.Model): 
        school = models.ForeignKey(School, on_delete=models.CASCADE)
        students = models.ManyToManyField(Student) 
    

    其次,除非您有理由将 name.max_length 设置为 100,否则请将其设置为 255。

        name = models.CharField(max_length=255)
    

    我还设置了一个相关名称以使事情变得更容易

    class Classroom(models.Model): 
        school = models.ForeignKey(School, on_delete=models.CASCADE, related_name='classrooms')
        students = models.ManyToManyField(Student) 
    

    现在,解决你的问题。

    你的逻辑是说一所学校可以有很多学生,一个学生可以在很多学校注册(很奇怪,但我会应付),一个教室可以存在于学校内部,一个学校可以有多个教室,一个教室有很多学生。这是一个关键,你不需要在学校里保存学生,你可以使用类似的东西

    class School(models.Model): 
        name = models.CharField(max_length=100)
        students = models.ManyToManyField(Student) 
        
        @property
        def students(self):
            # iterate the class room, return a QS with all students from them
            # there're operators for union, but I'm using the function itself
            qs = Student.objects.none()
            for classroom in self.classrooms: # related name in action
                qs = qs.union(classroom.students)
    
            return qs
    

    我会添加一个注释,你想要的行为可以在一个信号中完成#DON'T DO THING,JUST KNOW IT

    More info

    【讨论】:

    • 感谢您的帮助
    • 很高兴它有帮助。
    猜你喜欢
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-11
    • 2018-12-22
    • 1970-01-01
    • 2022-01-22
    • 2021-03-16
    相关资源
    最近更新 更多