只写,只读django rest框架中的字段

use*_*989 53 django django-rest-framework

我有这样的模特:

class ModelA(models.Model):
    name = models.CharField()


class ModelB(models.Model):
    f1 = models.CharField()
    model_a = models.ForeignKey(ModelA)
Run Code Online (Sandbox Code Playgroud)

串行器:

class ASerializer(serializers.ModelSerializer):
    model_b_ids = serializers.CharField()
    class Meta:
        model = ModelA
        write_only_fields = ('model_b_ids',)
Run Code Online (Sandbox Code Playgroud)

观点:

class AView(CreateModelMixin, GenericViewSet):

    def perform_create(self, serializer): 
        model_b_ids = parse_somehow(serializer.validated_data["model_b_ids"])
        #do something...
Run Code Online (Sandbox Code Playgroud)

我得到的问题是"model_b_ids"

用户应在发送发布数据时提交.

我在perform_create中使用它来链接到相关模型.

但那不是ModelA中的"真正的专栏"所以当我试图保存它时会引发异常.

我尝试从validated_data弹出,然后再次在某处无法从模型中读取model_b_ids的错误.有没有正确使用这种领域的想法?

Dr *_*tan 73

纠正我,如果我错了,但我不认为django休息框架有Meta属性

write_only_fields

根据他们的文档,你设置只写extra_kwargs中的字段

例如

class UserSerializer(ModelSerializer):
    """
    ``Serializer`` for ``User`` ..
    """

    class Meta:
        model = User
        fields = ('id', 'email', 'first_name', 'last_name' ,'security_question', 'security_question_answer', 'password', 'is_active', 'is_staff')
        read_only_fields = ('is_active', 'is_staff')
        extra_kwargs = {
            'security_question': {'write_only': True},
            'security_question_answer': {'write_only': True},
            'password': {'write_only': True}
        }
Run Code Online (Sandbox Code Playgroud)


M.V*_*oid 47

根据Django REST Framework 文档:

ModelSerializer上的write_only_fields选项已移至PendingDeprecation并替换为更通用的extra_kwargs

这就是为什么建议这样做:你应该使用extra_kwargs:

extra_kwargs = {'model_b_ids': {'write_only': True}}
Run Code Online (Sandbox Code Playgroud)

要么:

 model_b_ids = serializers.IntegerField(write_only=True)
Run Code Online (Sandbox Code Playgroud)

  • @vabada我希望你的意思是哈希 (5认同)
  • 我刚刚将DRF从3.1.3更新到3.3.3,突然我的用户密码被发回(我在`write_only`元属性之前.你的解决方案解决了这个问题.谢谢! (2认同)

AKH*_*HEW 14

从 DRF v3 开始,将字段设置为只读或只写可以使用序列化器字段核心参数,如下所示。

核心论点

每个序列化器字段类构造函数至少采用这些参数。某些 Field 类采用额外的、特定于字段的参数,但应始终接受以下内容:

只读

只读字段包含在 API 输出中,但不应包含在创建或更新操作期间的输入中。序列化器输入中错误包含的任何“read_only”字段都将被忽略。

将其设置为 True 以确保在序列化表示时使用该字段,但在反序列化期间创建或更新实例时不使用该字段。

默认为 False

例如:

price = serializers.IntegerField(read_only=True)
Run Code Online (Sandbox Code Playgroud)

只写

将其设置为 True 以确保在更新或创建实例时可以使用该字段,但在序列化表示时不包括该字段。

默认为 False

例如:

company = serializers.PrimaryKeyRelatedField(write_only=True)
Run Code Online (Sandbox Code Playgroud)


cez*_*zar 8

可能你正在监督你ModelA拥有财产modelb_set。在 Django 中,您在一个模型类中描述关系。Django 通过降低目标模型的大小写并将其后缀为_set. 所以你可以这样做:

a = ModelA.objects.get(pk=1)
a.modelb_set.all()
Run Code Online (Sandbox Code Playgroud)

这将从 ModelA 中获取 ID(或主键)为 1 的元素并检索所有相关的 ModelB 元素。

您可以设置一个值related_name来覆盖默认值:

class ModelB(models.Model):
    f1 = models.CharField()
    model_a = models.ForeignKey(ModelA, related_name='model_b')
Run Code Online (Sandbox Code Playgroud)

在 DRF 中,您可以稍微调整您的序列化程序:

class ASerializer(serializers.ModelSerializer):
    model_b = serializers.PrimaryKeyRelatedField(many=True, read_only=False)

    class Meta:
        model = ModelA
        write_only_fields = ('model_b',)
Run Code Online (Sandbox Code Playgroud)

随着serializers.CharField()您不能发表值,并将其写入模式,因为它不是一个模型字段。

试试这个例子。修补匠和实验。它应该让您更接近解决方案。

编辑:我不太确定 Django 如何为 PascalCase 类名创建后向关系的名称。是model_b_set为了ModelB?或者是modelb_set吗?你可以试着找出来。


Dru*_*lan 5

您可以从文档中使用read_only

只读字段包含在 API 输出中,但不应在创建或更新操作期间包含在输入中。序列化程序输入中错误包含的任何“只读”字段都将被忽略。

将此设置为 True 以确保在序列化表示时使用该字段,但在反序列化期间创建或更新实例时不使用该字段。

默认为 False

例如:

我们可以在 Serializer 字段上使用它:

model_b_ids = serializers.IntegerField(read_only=True)
Run Code Online (Sandbox Code Playgroud)

或者我们可以在extra_kwargs

extra_kwargs = {
    'model_b_ids': {'read_only': True}
}
Run Code Online (Sandbox Code Playgroud)