我有以下代码
serializer.py
class ContactSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
many = kwargs.pop('many', True)
many = True
super(ContactSerializer, self).__init__(many=many, *args, **kwargs)
class Meta:
model = Contact
def validate(self, attrs):
# Check that the user in contact isn't the same as the parent user
if 'user' in attrs.keys() and 'parent_user' in attrs.keys() and attrs['user']:
if attrs['user'].pk == attrs['parent_user'].pk:
raise serializers.ValidationError("You can't add yourself as a contact")
return attrs
views.py
class ContactViewSet(viewsets.ModelViewSet):
queryset = Contact.objects.all()
serializer_class = ContactSerializer
authentication_classes = (TokenAuthentication,)
permission_classes = (permissions.IsAuthenticated, )
def get_queryset(self):
return Contact.objects.filter(parent_user=self.request.user.pk)
def create(self, request):
if isinstance(request.DATA, list):
for i, contact_data in enumerate(request.DATA):
# Get the user id from the request
request.DATA[i]['parent_user'] = self.request.user.pk
# Check if the contact is aleardy a user
if 'email' in contact_data:
try:
request.DATA[i]['user'] = User.objects.get(email=contact_data['email']).pk
except User.DoesNotExist, e:
pass
return super(ContactViewSet, self).create(request)
现在问题在于,当我在POST
中发送联系人列表时,没有创建任何对象,它只会发送无效对象的错误。例如:
的 POST
[
{
"first_name": "Eyad",
"last_name": "tttttt",
"email": "eyad@gmail.com"
},
{
"first_name": "Eyad",
"last_name": "mmmmmm",
"email": "eyad2@gmail.com"
}
]
返回
[
{},
{
"non_field_errors": [
"You can't add yourself as a contact"
]
}
]
我怎样才能返回这样的内容:
[
{
"created": true
},
{
"non_field_errors": [
"You can't add yourself as a contact"
]
}
]
这样,当调用API时,会创建有效对象,并且API调用者不必再次发送这些对象。
答案 0 :(得分:1)
我创建了CreateModelMixin
的子类来更改create
方法。
class BulkCreateModelMixin(mixins.CreateModelMixin):
"""
Create valid objects and return errors for invalid ones.
"""
def create(self, request, *args, **kwargs):
# The initial serializer
serializer = self.get_serializer(data=request.DATA)
return_list = []
for item in zip(serializer.errors, serializer.init_data):
# If item doesn't have errors
if not item[0]:
# Create a an individual serializer for the valid object and save it
object_serializer = self.get_serializer(data=[item[1]])
if object_serializer.is_valid():
self.pre_save(object_serializer.object)
self.object = object_serializer.save(force_insert=True)
self.post_save(self.object, created=True)
return_list.append(object_serializer.data[0])
else:
return_list.append(item[0])
# Status code
if serializer.errors:
return_status = status.HTTP_206_PARTIAL_CONTENT
else:
return_status = status.HTTP_201_CREATED
return Response(return_list, status=return_status)
然后将新的mixin添加到视图集
class ContactViewSet(viewsets.ModelViewSet, BulkCreateModelMixin):
..........
..........
答案 1 :(得分:0)
我用另一种方式解决了这个问题。
创建 2 个 mixin,一个用于视图(覆盖 create
方法,另一个用于 ListSerializer(覆盖 to_internal_value method
)。
所以我有:
class CreateListMixin:
"""Allows bulk creation of a resource."""
def get_serializer(self, *args, **kwargs):
if isinstance(kwargs.get('data', {}), list):
kwargs['many'] = True
return super().get_serializer(*args, **kwargs)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response({"result": serializer.data, "errors": serializer.errors_list},
status=status.HTTP_202_ACCEPTED, headers=headers)
class ErrorsListSerializerMixin:
error_list = []
def to_internal_value(self, data):
"""
List of dicts of native values <- List of dicts of primitive datatypes.
"""
if not isinstance(data, list):
message = self.error_messages['not_a_list'].format(
input_type=type(data).__name__
)
raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [message]
}, code='not_a_list')
if not self.allow_empty and len(data) == 0:
message = self.error_messages['empty']
raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: [message]
}, code='empty')
ret = []
errors = []
for item in data:
try:
validated = self.child.run_validation(item)
except ValidationError as exc:
errors.append({"error": exc.detail, "data": item})
else:
ret.append(validated)
if any(errors):
self.errors_list = errors
# raise ValidationError(errors)
return ret
views.py
class SKUMatchesView(CreateListMixin, viewsets.ModelViewSet):
......................
......................
serializers.py
class SKUMatchesListSerializer(ErrorsListSerializerMixin, serializers.ListSerializer):
.....................
.....................
因此,当我发布例如此数据时:
[{ "sku_customer_uid": "13864-20000000428265",
"company": 1,
"code": "123456784654654",
"marketplace": "ozon"
},
{ "sku_customer_uid": "13864-2000000042824",
"company": 1,
"code": "123456789*8",
"marketplace": "ozon"
}
]
我收到同样的回复:
{
"result": [
{
"id": 8821,
"sku_customer_uid": null,
"company": 1,
"code": "123456784654654",
"marketplace": "ozon"
}
],
"errors": [
{
"error": {
"non_field_errors": [
"Wrong code"
]
},
"data": {
"sku_customer_uid": "13864-2000000042824",
"company": 1,
"code": "123456789*8",
"marketplace": "ozon"
}
}
]
}