Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django Rest框架-如何使用更新或创建_Python_Django_Django Rest Framework - Fatal编程技术网

Python 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

我正在使用Django Rest框架。我想创建记录,如果它不存在,或者更新,如果它存在

我所做的:

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

如果您确实需要更复杂的内容,那么您需要查看以正确管理事务(使用其
进行更新
锁定)并避免不必要的数据库查询。

也可以。我看到您的代码的唯一问题是它不尊重对象级权限。有关更多详细信息,请参阅