[英]Django Rest Framework ModelSerializer custom serializer field to_internal_value doesn't save to object
I have model and serializer, there is ArrayField(postgres) in that model. 我有模型和序列化器,该模型中有ArrayField(postgres)。
Now I wanted to create a serializer field that will receive list [1,2]
and save it to object, but for a list and detail in serializer to show a list of JSON objects. 现在,我想创建一个序列化器字段,该字段将接收列表
[1,2]
并将其保存到对象,但是要在序列化器中获取列表和详细信息以显示JSON对象列表。
Model: 模型:
class User(models.Model):
email = models.EmailField('Email', unique=True, blank=False)
full_name = models.CharField(
'Full name', max_length=150, blank=True, null=True)
roles = ArrayField(
models.PositiveSmallIntegerField(),
default=list,
blank=True
)
Serializer: 串行:
class ArraySerializerField(ListField):
def __init__(self, queryset, serializer_class):
super(ArraySerializerField, self).__init__()
self.queryset = queryset
self.serializer_class = serializer_class
def to_representation(self, value):
if value:
qs = self.queryset.filter(pk__in=value)
return self.serializer_class(qs, many=True).data
return []
def to_internal_value(self, value):
super(ArraySerializerField, self).to_internal_value(value)
print(value) # [1, 2]
return value
class UserSerializer(SerializerExtensionsMixin, serializers.ModelSerializer):
roles = ArraySerializerField(queryset=Role.objects.all(), serializer_class=RoleSerializer)
class Meta:
model = User
fields = ('id', 'email', 'full_name', 'roles')
def create(self, validated_data):
print(validated_data)
# {'email': 'test@test.com', 'full_name': 'Test', 'roles': []}
user = super(UserSerializer, self).create(validated_data)
return user
Now when I do list or detail request, everything is ok, I get a list of roles as JSON. 现在,当我执行列表或详细信息请求时,一切正常,我得到了一个角色列表,如JSON。
But when I try to POST data and send with this data: 但是当我尝试发布数据并发送此数据时:
{
"email": "test@test.com",
"full_name": "Test",
"roles": [1, 2]
}
validated_data
in create
method shows roles always as []
and object is saved without roles, but print from to_internal_value
shows [1, 2]
. create
方法中的validated_data
始终将角色显示为[]
并且对象保存时没有角色,但是从to_internal_value
打印显示[1, 2]
。
What am I doing wrong? 我究竟做错了什么? It should save sent data because
to_internal_value
works fine. 它应该保存发送的数据,因为
to_internal_value
可以正常工作。
EDIT: 编辑:
GET and LIST response gives me right format: GET和LIST响应给了我正确的格式:
{
"id": 1,
"email": "test@test.com",
"full_name": "Test",
"roles": [
{
"id": 1,
"name": "Role 1"
},
{
"id": 2,
"name": "Role 2"
}
]
}
Have you tried this? 你有尝试过吗?
class UserSerializer(SerializerExtensionsMixin, serializers.ModelSerializer):
roles = serializers.ListField(child=serializers.IntegerField(), allow_empty=True, required=False)
class Meta:
model = User
fields = ('id', 'email', 'full_name', 'roles')
def create(self, validated_data):
# check validated_data here
...
I'm not sure about the nature of SerializerExtensionsMixin
class here. 我不确定
SerializerExtensionsMixin
类的性质。 Also I'm not sure the intention behind the queryset
and serializer_class
arguments of your custom ListField
另外我不确定您的自定义
ListField
的queryset
和serializer_class
参数背后的意图
In [7]: from rest_framework import serializers
In [8]: class UserSerializer(serializers.Serializer):
# Created a simple serializer without model
...: roles = serializers.ListField(child=serializers.IntegerField(), allow_empty=True, required=False)
...: email = serializers.EmailField()
...: full_name = serializers.CharField()
...:
In [9]: data = {
# your data
...: "email": "test@test.com",
...: "full_name": "Test",
...: "roles": [1, 2]
...: }
In [10]: u = UserSerializer(data=data)
In [11]: u.is_valid()
Out[11]: True
In [12]: u.data
# got valid data
Out[12]: {'roles': [1, 2], 'email': 'test@test.com', 'full_name': 'Test'}
In [13]: data["roles"] = []
# change data to accept empty list
In [14]: u = UserSerializer(data=data)
In [15]: u.is_valid()
Out[15]: True
In [16]: u.data
# got validated data with empty list
Out[16]: {'roles': [], 'email': 'test@test.com', 'full_name': 'Test'}
In [17]: data["roles"] = ["foo","bar"]
#added string to the list
In [18]: u = UserSerializer(data=data)
In [19]: u.is_valid()
# validation failed
Out[19]: False
In [20]: u.errors
Out[20]: {'roles': {0: [ErrorDetail(string='A valid integer is required.', code='invalid')], 1: [ErrorDetail(string='A valid integer is required.', code='invalid')]}}
Create a RoleSerializer
and use it in the UserSerializer
创建一个
RoleSerializer
并在UserSerializer
class RoleSerializer(serializers.ModelSerializer): class Meta: model = Role fields = ('id', 'name')
class UserSerializer(SerializerExtensionsMixin, serializers.ModelSerializer):
roles = serializers.ListField(child=serializers.IntegerField(), allow_empty=True, required=False)
class Meta:
model = User
fields = ('id', 'email', 'full_name', 'roles')
def create(self, validated_data):
# check validated_data here
...
def to_representation(self, instance): rep = super().to_representation(instance) rep['roles'] = RoleSerializer(Role.objects.filter(id__in=rep['roles']), many=True).data return rep
Using a custom array field 使用自定义数组字段
class ArrayField(serializers.ListField): def __init__(self, *args, **kwargs): self.queryset = kwargs.pop('queryset', None) self.serializer_class = kwargs.pop('serializer_class', None) super().__init__(*args, **kwargs) def to_representation(self, data): qs = self.queryset.filter(id__in=data) serializer = self.serializer_class(qs,many=True) return serializer.data
class UserSerializer(SerializerExtensionsMixin, serializers.ModelSerializer):
roles = ArrayField(queryset=Role.objects.all(), serializer_class=RoleSerializer)
class Meta:
model = User
fields = ('id', 'email', 'full_name', 'roles')
def create(self, validated_data):
# check validated_data here
...
Try switching to PrimaryKeyRelatedField
. 尝试切换到
PrimaryKeyRelatedField
。 Though you'll need to change your user model to use an actual relation. 虽然您需要更改用户模型以使用实际关系。 Which is generally a good idea because it'll help enforce data integrity with your project.
通常这是一个好主意,因为它将帮助您的项目加强数据完整性。
class User(models.Model):
email = models.EmailField('Email', unique=True, blank=False)
full_name = models.CharField(
'Full name', max_length=150, blank=True, null=True)
roles = models.ManyToManyField(Role, blank=True)
class UserSerializer(SerializerExtensionsMixin, serializers.ModelSerializer):
roles = serializers.PrimaryKeyRelatedField(
many=True,
queryset=Role.objects.all(),
)
class Meta:
model = User
fields = ('id', 'email', 'full_name', 'roles')
def create(self, validated_data):
print(validated_data)
# {'email': 'test@test.com', 'full_name': 'Test', 'roles': []}
user = super(UserSerializer, self).create(validated_data)
return user
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.