【问题标题】:Django how to make each member of ManyToMany field unique?Django如何使ManyToMany字段的每个成员都是唯一的?
【发布时间】:2018-10-26 18:20:36
【问题描述】:

我正在开发一个程序员招聘网站,每个用户都可以在线完成编程案例并查看他们的结果。

这是我建立关系模型的方式(我省略了许多不重要的字段,只保留了有趣的字段):

这是我的候选班

class Candidate(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
cases = models.ManyToManyField(Case)

这是我的案例类

class Case(models.Model):
title = models.CharField(verbose_name="Titre", max_length=1000)
test1_complete = models.BooleanField(verbose_name="Test 1 Complété", default=False)
test2_complete = models.BooleanField(verbose_name="Test 2 Complété", default=False)
test3_complete = models.BooleanField(verbose_name="Test 3 Complété", default=False)
test4_complete = models.BooleanField(verbose_name="Test 4 Complété", default=False)

然后,我在用户面板上创建了两个候选人和一个案例,并通过 ManyToMany 字段将两个用户与案例相关联。 测试完成布尔字段是指用户是否完成了当前案例的每组​​测试。

这就是我如何在我的视图中获取每个用户的案例来修改它:

def fetch_cases_info(request):
first_case = Candidate.objects.filter(user=request.user).values_list("cases", flat=True) 
user_case = Case.objects.get(id=first_case)

我的问题是每个 Candidate 都有相同的 Case 对象,因此如果 User1 完成了 case 的 test1,那么每个 User 都会将其设置为 true。

我的目标是,当我对存储在候选人的 ManyToMany 字段中的案例进行更改时,它只会针对此案例进行更改,而不是针对使用此案例的每个人。

有没有人知道如何模拟这种关系? 我希望每个候选人都能够拥有多个案例,但它们应该是案例的唯一版本,以便我可以修改它的状态并且只影响一个候选人而不是每个人。

感谢您的回答。

【问题讨论】:

    标签: django django-models django-views


    【解决方案1】:

    ManyToManyField,除非您另外设置,否则将创建第三个表作为连接器。这是关系数据库知道如何建立多对多关系的唯一方法。 complete 布尔字段属于此连接器表,而不是两个多对多表中的任何一个。

    所以,不如做 Django 做的事,但要手动:为(例如)练习制作模型;说每个候选人可以有很多练习,但每个练习属于一个候选人;每个案例都在许多练习中完成,但每个练习都是一个案例。然后将您的布尔值粘贴在练习表上。然后,您可以根据需要将 ManyToManyField 与through='Exercise' 结合起来,以便您可以方便地访问candidate.cases,反之亦然,因为您知道它的实际作用。

    tl;dr:ManyToManyField 是一个 hack。手动执行以了解正在发生的事情(并能够将连接器用于自己的字段)。

    【讨论】:

      【解决方案2】:

      您可以在 ManyToManyField 中使用 through 参数,但我建议稍微更改架构。我在这里做一个假设,但为每个测试设置一个新列可能不是最好的主意(想想将来是否可以有更少或更多测试的案例)

      class Case(models.Model):
          title = models.CharField(verbose_name="Titre", max_length=1000)
      
      class TestCase(models.Model):
          case = models.ForeignKey(Case)
          number = models.PositiveIntegerField()
      
      class Candidate(models.Model):
          user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
          completed_tests = models.ManyToManyField(TestCase)
      

      然后要找出给定案例解决了哪些测试,请执行

      candidate.completed_tests.filter(case=mycase)
      

      【讨论】:

        猜你喜欢
        • 2014-05-27
        • 1970-01-01
        • 2022-01-21
        • 1970-01-01
        • 2016-03-30
        • 2012-11-01
        • 2013-11-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多