【问题标题】:Django Rest Framework Serializers: read_only parameter has no effectDjango Rest Framework Serializers:read_only 参数无效
【发布时间】:2020-04-12 21:57:09
【问题描述】:

只读设置无法正常工作。

不管我用read_only_fields

read_only_fields = ('id', 'user', 'created_at', 'account_type', 'balance', 'iban')

read_only 用于每个序列化器字段:

class BankAccountSerializer(serializers.ModelSerializer):

    id = serializers.StringRelatedField(read_only=True) 
    user = serializers.StringRelatedField(read_only=True)
    created_at = serializers.SerializerMethodField(read_only=True)
    account_name = serializers.StringRelatedField(read_only=False)
    account_type = serializers.StringRelatedField(read_only=True)
    balance = serializers.StringRelatedField(read_only=True)
    iban = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = BankAccount
        fields = '__all__'

    def get_created_at(self, instance):
        return instance.created_at.strftime("%B %d %Y")

这是我的数据库模型的样子:

class BankAccount(models.Model):
    id = models.AutoField(primary_key=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.CASCADE,
                             related_name='bankaccounts')
    created_at = models.DateTimeField(auto_now_add=True)
    account_name = models.CharField(max_length=255)
    account_type = models.CharField(max_length=10,
                                    choices=POSITIONS)
    balance = models.DecimalField(decimal_places=2, max_digits=12)
    iban = models.CharField(max_length=22)

    def __str__(self):
        return str(self.iban)

我的权限等级如下:

permission_classes = [IsUserOrReadOnly, IsAuthenticated]

自定义 IsUserOrReadOnly 类看起来像这样:

class IsUserOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.user == request.user

我的序列化器/视图如下所示:

class BankAccountViewSet(viewsets.ModelViewSet):
    queryset = BankAccount.objects.all()
    lookup_field = "iban"
    serializer_class = BankAccountSerializer
    permission_class = [IsUserOrReadOnly, IsAuthenticated]

我从 api 端点(选项方法响应)得到的不是我期望的结果,这意味着字段 account_name 仍然是 "read_only": true,,这可以在可浏览的 api 输出中看到:

"actions": {
    "PUT": {
        "id": {
            "type": "field",
            "required": false,
            "read_only": true,
            "label": "Id"
        },
        "user": {
            "type": "field",
            "required": false,
            "read_only": true,
            "label": "User"
        },
        "created_at": {
            "type": "field",
            "required": false,
            "read_only": true,
            "label": "Created at"
        },
        "account_name": {
            "type": "field",
            "required": false,
            "read_only": true,
            "label": "Account name"
        },
        "account_type": {
            "type": "field",
            "required": false,
            "read_only": true,
            "label": "Account type"
        },
        "balance": {
            "type": "field",
            "required": false,
            "read_only": true,
            "label": "Balance"
        },
        "iban": {
            "type": "field",
            "required": false,
            "read_only": true,
            "label": "Iban"
        }
    }
}

这里有什么问题吗?

【问题讨论】:

  • 能否请您显示确切的序列化程序/视图。看起来你可能把设置放在了错误的地方。
  • @WillemVanOnsem 我已经用视图代码更新了问题
  • 你能添加你的 complte BankAccountSerializer class 吗?
  • @JPG 我已经用它更新了问题
  • 你也可以添加BankAccount模型吗?

标签: python django django-rest-framework permissions serialization


【解决方案1】:

您不必在序列化程序中指定所有模型字段,因为您使用的是 ModelSerializer
试试下面的序列化器,

class BankAccountSerializer(serializers.ModelSerializer):
    created_at = serializers.SerializerMethodField()

    class Meta:
        model = BankAccount
        fields = '__all__'
        read_only_fields = ('id', 'user', 'created_at', 'account_type', 'balance', 'iban')

    def get_created_at(self, instance):
        return instance.created_at.strftime("%B %d %Y")

【讨论】:

    【解决方案2】:

    【讨论】:

    • 谢谢!但是在 SlugRelatedField 中,slug_field 参数是必需的,这听起来有点不对劲。我也不需要嵌套字段...
    • 您可以拥有 2 个序列化程序 - 一个用于使用 StringRelatedField 读取,一个用于 使用可写字段写入 - 即字符串数组字段;并在序列化程序中编写 implement create() 方法来创建和保存相关实例。然后,在您的 视图中覆盖 [get_serializer_class()](https://www.django-rest-framework.org/api-guide/generic-views/#get_serializer_classself) 以根据请求方法选择要使用的序列化程序。
    • 对于通用视图 - OPTIONS 请求基本 SimpleMetadata - 恕我直言,应该使用 POST 序列化程序来获取可用的 api 选项
    猜你喜欢
    • 1970-01-01
    • 2018-06-05
    • 2014-10-27
    • 2020-01-10
    • 2017-02-26
    • 1970-01-01
    • 2014-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多