验证父序列化程序时会删除嵌套序列化程序的有效字段。我读了一些类似案例的StackOverflow帖子,但由于read_only=True
而不是我的CreateParentView(generics.CreateAPIView)
字段被删除了案件。
将有效对象发布到Http 400 Bad request
后,出现create()
错误。我最终调试了# parsed_data is a QueryDict prepared from request.POST and request.FILES
# to fit the nested serializers format.
-> serializer.is_valid(raise_exception=True)
(Pdb) parsed_data.keys()
odict_keys(['parent_field_1', 'parent_field_2', 'parent_field_3', 'child'])
(Pdb) from .serializers import CreateChildSerializer;
ch = parsed_data.get('child');
new_child = CreateChildSerializer(data = ch);
(Pdb) new_child.is_valid()
True
(Pdb) new_child.errors
{}
# the parent serializer is invalid and drops the 'child' key
(Pdb) serializer.is_valid();
False
(Pdb) serializer.data.keys()
odict_keys(['parent_field_1', 'parent_field_2', 'parent_field_3'])
方法。
400 (Bad Request), "{"child":["This field is required."]}"
回复是models.py
Dafuq,我刚刚为你提供了这个,而你,先生,放弃了它: - (
好的,让我们来看看View,Serializer和Model。 我正在使用一个玩具模型,我的真实模型太冗长了,无法在这里重现。
让我们从Child
开始 - Parent
和OneToOneField
模型的关系为# models.py
class Parent(models.Model):
objects = ParentManager()
user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
parent_field_1 = models.BooleanField()
parent_field_2 = models.CharField(max_length=10)
parent_field_3 = models.CharField(max_length=10)
class Child(models.Model):
objects = ChildManager()
parent = models.OneToOneField('Parent', on_delete=models.CASCADE)
child_field_1 = ...
。
# serializers.py
class CreateParentSerializer(serializers.ModelSerializer):
child = CreateChildSerializer()
class Meta:
model = Parent
fields = ('parent_field_1', 'parent_field_2', 'parent_field_3', 'child')
@transaction.atomic
def create(self, validated_data):
child_data = validated_data.pop('child')
user = self.context['request'].user
parent = Parent.objects.create(user=user, **validated_data)
Child.objects.create(parent=parent, **child_data)
return parent
序列化程序基本上是嵌套序列化程序的 DRF guide approach 。
# views.py
class CreateParentView(generics.CreateAPIView):
serializer_class = CreateParentSerializer
def create(self, request, *args, **kwargs):
parsed_data = self.parse_request_data(request)
serializer = self.get_serializer(data=parsed_data)
import pdb; pdb.set_trace()
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def parse_request_data(self, request):
data_dict = dict(request.data)
# renaming keys, adding FILES to reproduce required structure, verbose and irrelevant
parsed_data = QueryDict('', mutable=True)
parsed_data.update(data_dict)
return parsed_data
最后是观点。
text()
我没有想法:X
答案 0 :(得分:0)
实际上,在这里张贴就像一个魅力......
我偶然发现了this GitHub线程来解决这个问题。
QueryDict仅用于不支持嵌套对象的多部分输入。
我必须使用FILES传输嵌套对象,因此使用了multipart / form-data并需要parse_request_data(request)
方法。修改方法以返回普通dict
而不是QueryDict
后,一切都顺利进行。
def parse_request_data(self, request):
data_dict = dict(request.data)
# renaming keys, adding FILES to reproduce required structure, verbose and irrelevant
### parsed_data = QueryDict('', mutable=True)
### parsed_data.update(data_dict)
return data_dict