django - 扩展django rest框架以允许在嵌套序列化程序中继承上下文

标签 django python-2.7 serialization django-rest-framework

我正在使用Django 1.6(很快会升级到1.8),Python 2.7和DRF 3.2.5(很快会升级到最新版本)。

我有一组深度嵌套的序列化器(深约10个级别,共有20-30个要序列化的模型)。
我正在尝试向上下文添加一个 bool 标志,这将确定序列化的输出层次结构是详细的(包括所有模型的字段)还是基本的(仅部分字段)。

我编写了以下代码(部分代码段):

from rest_framework import serializers
from app.models import Institute, Department, Member

class MemberSerializer(serializers.ModelSerializer):
    def get_fields(self):
        fields = super(MemberSerializer, self).get_fields()
        if self.context['basic_view']:
            for field in ['height', 'weight']:
                del fields[field]
        return fields

    class Meta:
        model = Member
        fields = ('id', 'birth_date', 'height', 'weight')


class DepartmentSerializer(serializers.ModelSerializer):
    members = MemberSerializer(many=True, read_only=True)

    def get_fields(self):
        fields = super(DepartmentSerializer, self).get_fields()
        if self.context['basic_view']:
            for field in ['type', 'manager']:
                del fields[field]
        return fields

    class Meta:
        model = Department
        fields = ('id', 'name', 'type', 'manager', 'members')


class InstituteSerializer(serializers.ModelSerializer):
    departments = DepartmentSerializer(many=True, read_only=True)

    def get_fields(self):
        fields = super(InstituteSerializer, self).get_fields()
        if self.context['basic_view']:
            for field in ['name', 'type']:
                del fields[field]
        return fields

    class Meta:
        model = Institute
        fields = ('id', 'name', 'type', 'departments')

def get_entities(is_basic_view):
    institutes_list = Institute.objects.all()

    serializer = InstituteSerializer(institutes_list, many=True, read_only=True, context={'basic_view': is_basic_view})

    return serializer.data

但是随后发现,从“get_entities”传递到“InstituteSerializer”的“上下文”没有传递给嵌套的序列化器。
这意味着在上面的示例中-InstituteSerializer在“上下文”中具有“basic_view”,而MemberSerializer和DepartmentSerializer没有。

我在context in nested serializers django rest framework中找到了一个可行的解决方案:在每个嵌套字段(例如“部门”)中使用SerializerMethodField,并在“get_”方法中手动传递上下文。
该解决方案的我的问题是,它需要将此代码嵌入20-30次在我的代码中,最终使源代码行的数量增加一倍。

我的要求-如果有人拥有(或可以帮助实现)serializers.ModelSerializer的扩展名,它将在构造时获得一个附加参数,例如'inherit_context'。
然后,在类中(例如在“InstituteSerializer”中),我唯一需要更改的就是添加该参数:
class InstituteSerializer(serializers.ModelSerializer):
    departments = DepartmentSerializer(many=True, read_only=True, inherit_context=True)

    def get_fields(self):
        fields = super(InstituteSerializer, self).get_fields()
        if self.context['basic_view']:
            for field in ['name', 'type']:
                del fields[field]
        return fields

    class Meta:
        model = Institute
        fields = ('id', 'name', 'type', 'departments')

最佳答案

显然我错过了一些东西...
'context'已经继承了到嵌套的序列化程序...

但是,不适用于我的原因是因为作为嵌套的一部分,一些子序列化器是通过serializers.SerializerMethodField()定义的。
并且在这种情况下(仅!)上下文是而不是自动继承。

解决方案是在与每个SerializerMethodField相关的'get _...'方法内简单地传递'context':

class ParentSerializer(serializers.ModelSerializer):
    child = serializers.SerializerMethodField()

    def get_child(self, obj):
        child = ....
        serializer = ChildSerializer(instance=child, context=self.context)
        return serializer.data

PS-类似于我的DRF github问题是在不久前创建的:https://github.com/tomchristie/django-rest-framework/issues/2555

关于django - 扩展django rest框架以允许在嵌套序列化程序中继承上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35494555/

相关文章:

python - 如何在 python 中为 chrome 的 Selenium Webdriver 设置 luminati 代理?

django - 如何使用大规模数据限制 Django Admin.TabularInline 中的查询

javascript - Ember : Custom JSONAPISerializer

c# - 如何将自定义类存储到 Windows 应用商店应用程序中的 LocalSettings?

c# - Web API2 序列化异常

java - Android中的Django JsonResponse解析错误

javascript - Ajax、jQuery、Django。这是如何设置的?

python - 在使用 django-filter 进行过滤时如何将过滤后的值导出到 csv 文件中

python - Django 和 weasyprint,合并 pdf

Python Numpy intersect1d 一维数组与二维数组