Django Rest Framework 类别和子级在一个模型中

标签 django django-rest-framework parent-child django-queryset

我有一个非常简单(乍一看)的问题。案例 - 一种产品可以在多个地方(商店)销售,并且每种产品都可以在具有不同类别和子类别的单个商店中表示(这就是为什么类别通过foreignkey与分类链接两次)。 这是我的分类模型,有几个 FK。

class Assortment(models.Model):

    category = models.ForeignKey('category.Category', null=True, blank=True, default=None,related_name='assortment_child')
    parent_category = models.ForeignKey('category.Category', null=True, blank=True, default=None,related_name='assortment_parent')
    product = models.ForeignKey(Product)
    shop = models.ForeignKey(Shop)

View ,基于rest_framework.generics.ListAPIView

class InstitutionTreeCategories(generics.ListAPIView):
    """Resource to get shop's tree of categories."""

    serializer_class = serializers.InstitutionCategoriesSerializer

    def get_queryset(self):
        shop = self.get_shop()
        return Category.objects.filter(assortment_parent__shop=shop).distinct()

最后,序列化器

class CategoryListSerializer(serializers.ModelSerializer):

    class Meta:
        """Meta class."""

        model = Category
        fields = ('id', 'name', 'image')


class CategoriesTreeSerializer(CategoryListSerializer):

    # childs = CategoryListSerializer(many=True, source='assortment_child__parent_category')
    childs = serializers.SerializerMethodField()

    class Meta(CategoryListSerializer.Meta):
        """Meta class."""

        fields = ('id', 'name', 'image', 'childs')

    def get_childs(self, obj):
        qs = Category.objects.filter(assortment_child__parent_category=obj.id).distinct()
        return CategoryListSerializer(qs, many=True, context=self.context).data

我需要使用我的 API 显示单个商店的类别树。 但问题是 - 如果我使用serializer.SerializerMethodField - 它可以工作,但是查询太多(对于每个父类别)。我尝试使用“源”选项和“CategoryListSerializer”来避免它,但我无法做到。每次,我都会得到 - 'Category' object has no attribute assortment_child__parent_category。在我尝试过的外壳模型中

In [8]: cat.assortment_parent.values('category').distinct()
Out[8]: (0.003) SELECT DISTINCT "marketplace_assortment"."category_id" FROM "marketplace_assortment" WHERE "marketplace_assortment"."parent_category_id" = 4 LIMIT 21; args=(4,)
<AssortmentQuerySet [{'category': 3}]>

所以 - 类别对象有这个属性,当然有,我用了它的 get_childs 方法。所以问题是 - 我如何将它与serializer.ModelSerializer 及其源选项一起使用? (当然使用 select_lated 方法和查询集,以避免过多的查询)。

最佳答案

根据源选项,您应该使用 . 而不是 __:

childs = CategoryListSerializer(many=True, source='assortment_child.parent_category')

但您仍然会有很多疑问,要修复它,您应该使用 prefetch-related

def get_queryset(self):
    shop = self.get_shop()
    qs = Category.objects.filter(assortment_parent__shop=shop).all()
    return qs.prefetch_related('assortment_child').distinct()

更多详细信息,您可以阅读 how-can-i-optimize-queries-django-rest-framework

关于Django Rest Framework 类别和子级在一个模型中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51010114/

相关文章:

python - Postgresql:将本地数据库迁移到 PythonAnywhere 数据库

django - 无法使用 View 名称 (django-rest-framework) 解析超链接关系的 URL

amazon-s3 - Boto3 ContentDisposition 内联不起作用

python - 在django rest framework中加入相关模型

javascript - 如何将平面对象数组(可能有多个父对象)转换为嵌套对象数组

c++ - 从 C++ 中的子窗体访问父函数

python - django 中项目主管的路径

python - Django 模板中的外键关系

python - 在保存之前编辑 django-rest-framework 序列化程序对象

php - Elasticsearch查询日期排序父子关系(重复事件)