首页 > 解决方案 > 如何在 Django Rest Framework 中使用 SerializerMethodField 进行更新

问题描述

我的 ModelSerializer 中有一个字段,我将其设置为 SerializerMethodField 以修改该字段的获取行为。我以前可以更新数据,现在我不能。我该如何解决这个问题?

最初,没有使用 SerializerMethodField,我得到了这样的数据:

    {
        ...
        "members": [2,3],
        ...
    }

但我添加了 SerializerMethodField 来修改数据,然后更新停止工作。

模型.py

# Create your models here.
class Company(models.Model):
    members = ArrayField(models.IntegerField(blank=True), blank=True)
...

序列化程序.py

class AccountSerializer(serializers.ModelSerializer):
    user=serializers.StringRelatedField(read_only=False)
    class Meta:
        model=Account
        fields='__all__'

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

class CompanySerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=False)
    members = serializers.SerializerMethodField()
    class Meta:
        model = Company
        fields = '__all__' #('id', 'name', 'description', 'date_created', 'user', 'status', 'theme', 'members')

    def get_members(self, obj):
        accounts = Account.objects.filter(id__in=obj.members)
        return AccountSerializer(accounts, many=True).data
...

标签: pythondjangodjango-rest-framework

解决方案


  1. 您需要使用不同的序列化程序进行更新和创建。此序列化程序仅适用于 get。

  2. 或者,您可以创建自定义字段。Django Rest Framework 如何更新 SerializerMethodField

  3. 或者,可以有其他更简单的钩子。如果 'create' 和 'update' 在修改之前按您的意愿工作members,那么您可以执行以下操作以将创建和更新请求的所有内容设为默认值。

  • 覆盖__init__方法。.
class CompanySerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        try:
            if self.context['request'].method in ['GET']:
                self.fields['members'] = SerializerMethodField()
        except KeyError:
            pass

    class Meta:
        model = Company
        fields = '__all__' #('id', 'name', 'description', 'date_created', 'user', 'status', 'theme', 'members')

    def get_members(self, obj):
        accounts = Account.objects.filter(id__in=obj.members)
        return AccountSerializer(accounts, many=True).data
...
  • 或者,您可以创建不同的字段来获取成员。
class CompanySerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=False)
    members_data = SerializerMethodField()

    class Meta:
        model = Company
        fields = ('id', 'name', 'description', 'date_created', 'user', 'status', 'theme', 'members', 'members_data')

    def get_members_data(self, obj):
        accounts = Account.objects.filter(id__in=obj.members)
        return AccountSerializer(accounts, many=True).data
...

推荐阅读