【问题标题】:Django rest framework serializer ignores extra_kwargs or custom attributeDjango rest 框架序列化程序忽略 extra_kwargs 或自定义属性
【发布时间】:2020-03-22 08:51:58
【问题描述】:

我正在尝试为客户端和主要用户制作一个略有不同的 api。所以如果角色是客户端,我想稍后添加客户端。

class StoreSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Store
        fields = ["id", "name", "location", "location_lat", "location_lng", "client"]

    def create(self, validated_data):
        user = self.context["request"].user
        if user.role == Roles.CLIENT.name:
            validated_data["client"] = user.client

简化后的模型是这样的

class Store(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE)

当我现在使用具有角色客户端的用户调用序列化程序时,我得到以下响应:

{"client":["This field is required."]}

这是正确的。但是当我将extra_kwargs 添加到 StoreSerializer 时,奇怪的事情发生了。如果我将序列化程序更改为:

class StoreSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Store
        fields = ["id", "name", "location", "location_lat", "location_lng", "client"]
        extra_kwargs = {
            "client": { "required": False }
        }

    def create(self, validated_data):
        user = self.context["request"].user
        if user.role == Roles.CLIENT.name:
            validated_data["client"] = user.client

或者改成

class StoreSerializer(serializers.ModelSerializer):
    client = serializers.UUIDField(required=False)

    class Meta:
        model = models.Store
        fields = ["id", "name", "location", "location_lat", "location_lng", "client"]

    def create(self, validated_data):
        user = self.context["request"].user
        if user.role == Roles.CLIENT.name:
            validated_data["client"] = user.client

我得到了同样的回应。怎么会这样?客户端不应该是必需的吧?

版本:

  • Django:2.2.3
  • Django 休息框架:3.9.4

【问题讨论】:

  • 您是否尝试将客户端外键设置为允许 null 和空白?
  • 是的,但只是在序列化程序中。我没有在模型中尝试过。但显然我不想要那个
  • 当您提出这些请求时,客户端是否被设置为任何内容和/或 user.role 是否等于 Roles.CLIENT?
  • 在我的情况下,用户是客户端,这意味着用户模型具有客户端属性。如果用户没有角色客户端,则意味着他已经向客户端发送了请求。如果这有意义?
  • 无法复制。这是哪个 DRF 版本?另外请在后两种情况下添加整个StoreSerializer 定义,以及您正在传递的data 示例。

标签: django django-rest-framework django-serializer


【解决方案1】:

如果你说的是正确的,那么我会弹出该字段。无论如何可能是最好的,这样当用户没有被授权时,API 资源管理器就不会包含它。

class StoreSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Store
        fields = ["id", "name", "location", "location_lat", "location_lng", "client"]

    def __init__(*args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.context["request"].user.role == Roles.CLIENT.name:
            del self.fields["client"]

    def create(self, validated_data):
        user = self.context["request"].user
        if user.role == Roles.CLIENT.name:
            validated_data["client"] = user.client

【讨论】:

  • 当该字段以required=False 初始化或在extra_kwargs 中提及时,该字段不应提出此类投诉。完全删除该字段不会以任何方式解决根本原因。
  • 同意它不应该那样工作,但绝对不同意它不能解决他们的问题。如果无法填充客户端的用户浏览到可浏览 API,他们甚至不应该看到选择客户端的选项。实现这一目标的唯一方法是删除该字段。
【解决方案2】:

商店模型应该是这样的:(注blank

class Store(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE, blank=True)

现在在数据库级别,您允许客户端在 Store 模型中为空。

这样的序列化器:

class StoreSerializer(serializers.ModelSerializer):
    client = serializers.PrimaryKeyRelatedField(queryset=models.Client.objects.all(), required=False)

    class Meta:
        model = models.Store
        fields = ["id", "name", "client"]
    ...

您的序列化程序现在应该可以工作了。

【讨论】:

    猜你喜欢
    • 2019-05-20
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    相关资源
    最近更新 更多