【问题标题】:Unique values across ManyToMany fields on DjangoDjango上ManyToMany字段的唯一值
【发布时间】:2014-05-27 01:31:06
【问题描述】:

我需要一些帮助来解决一个非常简单的问题(解释起来很简单,但不是为我解决)

我在 Django 中有以下模型:

class ClassGroup(models.Model):
    group = models.CharField(_('group'), max_length=3)
    course = models.ForeignKey(Course,
                               related_name='classgroups',
                               related_query_name='classgroup',
                               verbose_name=_('course'))
    students = models.ManyToManyField(Actor,
                                      related_name='student_classgroups',
                                      related_query_name='student_classgroup',
                                      verbose_name=_('student'))
    lecturers = models.ManyToManyField(Actor,
                                       related_name='lecturer_classgroups',
                                       related_query_name='lecturer_classgroup',
                                       verbose_name=_('lecturer'))

    class Meta:
        verbose_name = _('class group')
        verbose_name_plural = _('class groups')
        unique_together = ('group', 'course')

我需要添加一个约束,以防止 Actor 在每个 ClassGroup 中同时成为学生和讲师。是否可以在模型级别添加这样的约束?如果可能的话,我想避免上层基于表单/视图的解决方案。

非常感谢!

【问题讨论】:

    标签: django model many-to-many constraints unique


    【解决方案1】:

    我认为没有任何方法可以在 Django 的数据库级别指定它。您可以在模型的 clean()validate_unique() 方法中检查这一点,但这些方法仅在特定情况下被调用。

    一种方法是重组您的数据库,以便为学生和讲师使用一个表,并使用role 列进行区分。

    class ClassGroup(models.Model):
        group = models.CharField(_('group'), max_length=3) 
        course = models.ForeignKey(Course, related_name='classgroups', 
                                           related_query_name='classgroup',
                                           verbose_name=_('course')) 
        actors = models.ManyToManyField(Actor, related_name='classgroups',
                                               through='ClassRole')
    
    
        class Meta: 
            verbose_name = _('class group') 
            verbose_name_plural = _('class groups') 
            unique_together = ('group', 'course')
    
    class ClassRole(models.Model):
        class_group = models.ForeignKey(ClassGroup, related_name='roles')
        actor = models.ForeignKey(Actor, related_name='roles')
    
        STUDENT_ROLE = 10
        LECTURER_ROLE = 20
        ROLE_CHOICES = (
            (STUDENT_ROLE, _('student role')),
            (LECTURER_ROLE, _('lecturer role')),
        )
        role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES)
    

    在这种结构中,每个演员当然只有一个角色。您还可以编写自定义的Managers 和模型方法,以便轻松获取学生或讲师。

    【讨论】:

    • 非常感谢您的快速回答。你的解决方案无疑是非常好的,但是我和我的团队在我们的项目中处于先进的状态,所以我们希望避免模型更改,因为我们需要重构很多东西。但是,我们会检查是否有可能继续您的想法。如果不是,那么我认为我们将定义一个 clean() 方法(这实际上很糟糕,但我们没有更好的主意)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-18
    • 2017-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多