如何制作可以处理 Create API 端点的嵌套 post 数据的自定义序列化程序?
how to make custom serializer which can handle nested post data for Create API endpoint?
由于独特的业务需求,我必须自定义创建 API 端点。
django-rest-framework 中的默认行为是这样的。
class Customer(models.Model):
fieldA = models.IntegerField(null=True, blank=True)
fieldB = models.CharField(max_length=5, blank=True)
... ...
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = '__all__'
class CustomerListCreateAPIView(generics.ListCreateAPIView):
queryset = Customer.objects.all()
serializer_class = CustomerSerializer
post数据
{
fieldA: 1,
fieldB: 'some string'
}
它发送带有已创建状态的响应
{
id: 1,
fieldA: 1,
fieldB: 'some string'
}
但是,我想post数据嵌套数据并验证
{
"customer": {
"fieldA": 1,
"fieldB": "some string"
}
}
预期的响应数据应该是
{
"customer": {
"id": 1,
"fieldA": 1,
"fieldB": "some string"
}
}
验证还应显示嵌套的错误消息
{
"customer": "customer field is required"
}
{
"customer": {
"fieldA": ["filedA is required"],
}
}
我该如何存档?
您可以创建一个 ApiView 并通过迭代验证每个数据。
如果所有数据都有效,则创建对象。
示例:
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = '__all__'
class CustomerListCreateAPIView(APIView):
def post(self, request, *args, **kwargs):
customers = request.data.get('customer', None)
for customer in customers:
validated_data = CustomerSerializer(data=customer)
# if invalid Raise Validation error
objects = []
for customer in customers:
validated_data = CustomerSerializer(data=customer)
customer = Customer.objects.create(validated_data)
objects.append(customer.id)
return Response(
CustomerSerializer(Customer.objects.filter(id__in=objects), many=True).data)
这是我修改后的方法。它使用序列化程序创建新实例并发送嵌套验证错误消息。
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = '__all__'
class CustomerView(generics.ListCreateAPIView):
queryset = Customer.objects.all()
def create(self, request, *args, **kwargs):
customer = request.data.get('customer', None)
if not customer:
raise serializers.ValidationError({'customer': 'customer field is required'})
serializer = CustomerSerializer(data=customer)
serializer.is_valid(raise_exception=False)
if serializer.errors:
error = {
'customer': serializer.errors
}
return Response(error, status=status.HTTP_400_BAD_REQUEST)
data = serializer.save()
headers = self.get_success_headers(serializer.data)
return Response(data, status=status.HTTP_201_CREATED, headers=headers)
验证错误:
{
"customer": "customer field is required"
}
{
"customer": {
"fieldA": ["filedA is required"],
}
}
希望这对其他人有所帮助。
由于独特的业务需求,我必须自定义创建 API 端点。 django-rest-framework 中的默认行为是这样的。
class Customer(models.Model):
fieldA = models.IntegerField(null=True, blank=True)
fieldB = models.CharField(max_length=5, blank=True)
... ...
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = '__all__'
class CustomerListCreateAPIView(generics.ListCreateAPIView):
queryset = Customer.objects.all()
serializer_class = CustomerSerializer
post数据
{
fieldA: 1,
fieldB: 'some string'
}
它发送带有已创建状态的响应
{
id: 1,
fieldA: 1,
fieldB: 'some string'
}
但是,我想post数据嵌套数据并验证
{
"customer": {
"fieldA": 1,
"fieldB": "some string"
}
}
预期的响应数据应该是
{
"customer": {
"id": 1,
"fieldA": 1,
"fieldB": "some string"
}
}
验证还应显示嵌套的错误消息
{
"customer": "customer field is required"
}
{
"customer": {
"fieldA": ["filedA is required"],
}
}
我该如何存档?
您可以创建一个 ApiView 并通过迭代验证每个数据。 如果所有数据都有效,则创建对象。
示例:
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = '__all__'
class CustomerListCreateAPIView(APIView):
def post(self, request, *args, **kwargs):
customers = request.data.get('customer', None)
for customer in customers:
validated_data = CustomerSerializer(data=customer)
# if invalid Raise Validation error
objects = []
for customer in customers:
validated_data = CustomerSerializer(data=customer)
customer = Customer.objects.create(validated_data)
objects.append(customer.id)
return Response(
CustomerSerializer(Customer.objects.filter(id__in=objects), many=True).data)
这是我修改后的方法。它使用序列化程序创建新实例并发送嵌套验证错误消息。
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = '__all__'
class CustomerView(generics.ListCreateAPIView):
queryset = Customer.objects.all()
def create(self, request, *args, **kwargs):
customer = request.data.get('customer', None)
if not customer:
raise serializers.ValidationError({'customer': 'customer field is required'})
serializer = CustomerSerializer(data=customer)
serializer.is_valid(raise_exception=False)
if serializer.errors:
error = {
'customer': serializer.errors
}
return Response(error, status=status.HTTP_400_BAD_REQUEST)
data = serializer.save()
headers = self.get_success_headers(serializer.data)
return Response(data, status=status.HTTP_201_CREATED, headers=headers)
验证错误:
{
"customer": "customer field is required"
}
{
"customer": {
"fieldA": ["filedA is required"],
}
}
希望这对其他人有所帮助。