【问题标题】:querysets in models with manytomany fields (Django)具有多字段的模型中的查询集(Django)
【发布时间】:2018-10-06 13:57:08
【问题描述】:

我的问题与在多对多领域相互关联的模型上创建查询集有关。

context - 学生进入并必须对他或她的老师进行评分的应用程序。该应用程序向学生显示的问题具有以下逻辑:每个学生必须评价一些老师。每个老师都有不同类别的问题与他们相关联(“智力”、“尊重”、“同理心”等),每个类别都有一些与之相关的问题。

模型是:

class Items(models.Model):
     item = models.TextField()
     def __str__(self):
          return self.item

class Categories(models.Model):
    category = models.CharField(max_length=50,null=True)
    items_associated  = models.ManyToManyField(Items)
    def __str__(self):
       return self.category

class Professors(models.Model):
    professor = models.CharField(max_length=50,null=True)
    categories_assigned = models.ManyToManyField(Categories)
    def __str__(self):
       return self.professor

class Students(models.Model):
    student_logged = models.CharField(max_length=50,null=True)
    professors_to_evaluate = models.ManyToManyField(Professors)
    def __str__(self):
       return self.student_logged

当学生进入网络时,有一些相关的教师(模型学生),这些教师又分配了一些类别(模型教授),这些类别又关联了一些问题(模型类别)。 我想将模型项目中的这些问题存储在字典中。我该怎么做?

我尝试过过滤和 __in,但我无法得到它。

非常感谢,感谢您的智慧

【问题讨论】:

  • 您想要Students 对象有权访问的所有项目吗?只是澄清一下,因为有点不清楚你想要的最终结果是什么。

标签: django django-models many-to-many django-queryset


【解决方案1】:

我强烈建议您使用related_name 属性。我在相关名称中添加了_x,以使查询更加明显。

class Items(models.Model):
     item = models.TextField()
     def __str__(self):
          return self.item

class Categories(models.Model):
    category = models.CharField(max_length=50,null=True)
    items_associated  = models.ManyToManyField(Items, related_name='category_x')
    def __str__(self):
       return self.category

class Professors(models.Model):
    professor = models.CharField(max_length=50,null=True)
    categories_assigned = models.ManyToManyField(Categories, related_name='professor_x')
    def __str__(self):
       return self.professor

class Students(models.Model):
    student_logged = models.CharField(max_length=50,null=True)
    professors_to_evaluate = models.ManyToManyField(Professors, related_name='student_x')
    def __str__(self):
       return self.student_logged

items_for_student = Items.objects.filter(category_x__professor_x__student_x=student)

但您用于字段的命名约定也有点古怪。我在下面使用了最佳做法,因此您可以看到它的样子。

  1. 没有与模型同名的字段
  2. 模型应该是单数(极少数例外)
  3. ManyToMany 或 ForeignKey 关系应共享模型的名称,以便查询自身文档。

有了这些规则,最佳实践就是这样。

class Item(models.Model):
     name = models.TextField()
     def __str__(self):
          return self.name

class Category(models.Model):
    name = models.CharField(max_length=50,null=True)
    items = models.ManyToManyField(Item, related_name='categories')
    def __str__(self):
       return self.name

class Professor(models.Model):
    name = models.CharField(max_length=50,null=True)
    categories = models.ManyToManyField(Category, related_name='professors')
    def __str__(self):
       return self.name

class Student(models.Model):
    name = models.CharField(max_length=50,null=True)
    professors = models.ManyToManyField(Professor, related_names='students')
    def __str__(self):
       return self.name

使用这种结构,查询将如下所示:

items = Item.objects.filter(categories__professors__students=student)

另外请注意,上述查询在数据库上运行会非常昂贵,因为它会评估为 3 个连接。

【讨论】:

  • 非常感谢您的回答。关于您所说的查询将非常昂贵,还有哪些其他选择可以降低搜索成本?
  • @Ale 如果不更改架构以使数据非规范化,您将无法做很多事情。您可以为模型添加索引,这将在一定程度上加快速度。 docs.djangoproject.com/en/2.0/ref/models/options/…
  • 感谢您的大力帮助。当您说“更改架构以使数据非规范化”时,这意味着例如加入同一模型中的模型“类别”和“项目”。这个(加入模型)的优缺点是什么?
猜你喜欢
  • 1970-01-01
  • 2011-10-27
  • 1970-01-01
  • 2019-06-17
  • 1970-01-01
  • 2011-02-02
  • 1970-01-01
  • 2013-05-17
  • 2020-03-05
相关资源
最近更新 更多