Python Django Rest框架-如何使用更新或创建
我正在使用Django Rest框架。我想创建记录,如果它不存在,或者更新,如果它存在 我所做的:Python Django Rest框架-如何使用更新或创建,python,django,django-rest-framework,Python,Django,Django Rest Framework,我正在使用Django Rest框架。我想创建记录,如果它不存在,或者更新,如果它存在 我所做的: class MyModelList(generics.ListCreateAPIView): queryset = MyModel.objects.all() serializer_class = MyModeSerializer permission_classes = (permissions.IsAuthenticated,) def perform_cre
class MyModelList(generics.ListCreateAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModeSerializer
permission_classes = (permissions.IsAuthenticated,)
def perform_create(self, serializer):
my_model, created = MyModel.objects.update_or_create(user_id=self.request.data['user_id'],
defaults={
'reg_id': self.request.data['reg_id']
})
记录已创建或更新。但是我得到一个错误,
“OrderedDict”对象没有属性“pk”
首先,这是一个坏主意,因为你打破了REST API标准,该标准要求通过POST创建,并通过PUT和PATCH更新
但是,假设您有很好的理由这样做,perform\u create
将在创建后被调用,以添加在添加模型实例时需要执行的其他操作。更相关的事情是重写create方法,以便在必要时更新对象
我会这样做的
class MyModelList(generics.ListCreateAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModeSerializer
permission_classes = (permissions.IsAuthenticated,)
def create(self, request, *args, **kwargs):
mymodel=None
id=request.data.get("id")
if id:
mymodel=self.get_object(id)
if mymodel:
return self.update(request, *args, **kwargs)
else:
return self.create(request, *args, **kwargs)
谢谢@Bitonator。这是我的最终解决方案:
class MyModelList(generics.ListCreateAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModeSerializer
permission_classes = (permissions.IsAuthenticated,)
def create(self, request, *args, **kwargs):
myMode, created = MyModel.objects.update_or_create(user_id=request.data['user_id'],
defaults={
'reg_id': request.data['reg_id']
})
# require context={'request': request} because i'm using HyperlinkModelSerializer
serializer = MyModelSerializer(myModel, data=request.data, context={'request': request})
if serializer.is_valid():
serializer.save()
if created:
return Response(serializer.data, status.HTTP_201_CREATED)
else:
return Response(serializer.data, status.HTTP_200_OK)
我同意相关讨论的结论,并将PUT作为upsert实施
这意味着:
def put(…):
将调用self.upsert(…)
方法与def post(…):
调用self.create(…)
相同
def upsert(…)
将调用self。执行\u upsert(序列化程序)
,类似于
如果您想要部分更新,这里有一个棘手的问题;在这种情况下,您可能还希望只使用sql-更新
;以及其他并发症
因此,对于非部分更新,def perform\u upsert(序列化程序):
将调用serializer.upsert()
如果你愿意的话,这里还有一个复杂问题,即关系
您可能需要指定要用作键的字段
生成的序列化程序如下所示:
class MyModelSerializer(serializers.ModelSerializer):
…
_key_attrs = ('username',) # the effective primary key, such as auth_user's username.
def upsert(self):
assert not self.errors
validated_data = self.validated_data
effective_key = {key: validated_data.get(key) for key in self._key_attrs}
instance, _ = model.objects.update_or_create(defaults=validated_data, **effective_key)
return instance
如果您确实需要更复杂的内容,那么您需要查看以正确管理事务(使用其
进行更新锁定)并避免不必要的数据库查询。也可以。我看到您的代码的唯一问题是它不尊重对象级权限。有关更多详细信息,请参阅