首页 > 解决方案 > DJango 查询外键优化

问题描述

class MainCategory(models.Model):
    main_category_id = models.PositiveSmallIntegerField(primary_key=True)
    name = models.CharField(max_length=30)
    image = models.URLField(null=True)

    class Meta:
        db_table = 'lookup_main_category'

    def __str__(self):
        return self.name

class SubCategory(models.Model):
    sub_category_id = models.PositiveSmallIntegerField(primary_key=True)
    main_category = models.ForeignKey(MainCategory, on_delete=models.CASCADE)
    name = models.CharField(max_length=50)
    image = models.URLField(null=True)

    class Meta:
        db_table = 'lookup_sub_category'

    def __str__(self):
        return self.name

我的 DJango REST 框架项目中有上述 2 个模型,我需要如下的 API 输出。如果没有典型的 for 循环来获得不同的主要类别,然后在 sub_category 表中遍历它,那么最佳查询是什么?

[
  {
    "main_category_id": "10",
    "main_category_name": "main_name1",
    "image": "http://example/com1",
    "sub_categories": [
      {
        "sub_category_id": "20",
        "sub_category_name": "sub_name1",
        "image": "http://example/com1"
      },
      {
        "sub_category_id": "21",
        "sub_category_name": "sub_name2",
        "image": "http://example/com"
      }
    ]
  },
  {
    "main_category_id": "11",
    "main_category_name": "main_name2",
    "image": "http://example/com2",
    "sub_categories": [
      {
        "sub_category_id": "22",
        "sub_category_name": "sub_name2",
        "image": "http://example/com2"
      }
    ]
  }
]

标签: djangodjango-modelsdjango-rest-framework

解决方案


在这种情况下,您将利用prefetch_related,它执行两个 SQL 查询并执行内存中的 JOIN。

queryset = MainCategory.objects.prefetch_related('subcategory_set')

然后你迭代这个查询集,用它的子类别序列化每个对象,而不会碰到数据库。

更多信息。官方文档在这里:https ://docs.djangoproject.com/en/3.0/ref/models/querysets/#prefetch-related


推荐阅读