我正在尝试使django-rest-framework接受一系列字典,以便在一个api调用中更新或创建许多对象。
我的模特:
class Order(models.Model):
internal_id = models.CharField(max_length=500, unique=True)
external_id = models.CharField(max_length=500, blank=True, null=True, unique=True)
status = models.CharField(max_length=500, blank=True, null=True)
我的序列化器:
class SimpleOrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = '__all__'
我的观点:
class CreateListMixin():
def get_serializer(self, *args, **kwargs):
if isinstance(kwargs.get('data', {}), list):
kwargs['many'] = True
return super().get_serializer(*args, **kwargs)
class OrderViewSet(CreateListMixin, viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = SimpleOrderSerializer
lookup_field = 'internal_id'
如果我发布带有新internal_id
值的字典列表,则此代码非常有用,但是如果我包含一个已经存在的值,我想更新该对象。 django-rest-framework有可能吗?
答案 0 :(得分:0)
是的,有可能,但是您必须在序列化程序上提供自己的create
方法。我建议您阅读"Customizing multiple create" part of the documentation。
创建多个对象的默认实现是简单地为列表中的每个项目调用
.create()
。如果要自定义此行为,则需要自定义.create()
传递时使用的ListSerializer
类的many=True
方法。
因此,您需要创建一个SimpleOrderListSerializer
来定义所需的行为,例如:
class SimpleOrderListSerializer(serializers.ListSerializer):
def create(self, validated_data):
orders = []
for item in validated_data:
# Assuming your "identifying" set of fields is only `internal_id`
internal_id = item.pop('internal_id')
order, created = Order.objects.update_or_create(
internal_id=internal_id,
defaults=item,
)
orders.append(order)
return orders
然后将此序列化器定义为SimpleOrderSerializer
的默认列表序列化器:
class SimpleOrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
list_serializer_class = SimpleOrderListSerializer
fields = '__all__'