如何在Django及DRF中使用PUT方法创建对象(含指定ID无对象场景)
嘿,针对你这两个关于Django和DRF中PUT方法的问题,我来分享下实际项目里常用的解决方案:
1. 如何在Django框架中使用PUT方法创建对象
Django原生视图并没有默认把PUT方法和对象创建绑定(通常PUT用于更新),所以需要我们自定义视图逻辑来实现。这里分两种常见场景:
基于函数的视图实现
from django.http import JsonResponse from .models import YourModel import json def create_or_update_view(request, pk=None): if request.method == "PUT": try: # 解析PUT请求的JSON数据 request_data = json.loads(request.body) # 方案1:如果传入了pk,用update_or_create实现"存在则更新,不存在则创建" if pk: obj, created = YourModel.objects.update_or_create( id=pk, defaults=request_data ) status_code = 201 if created else 200 return JsonResponse( {"id": obj.id, "status": "created" if created else "updated"}, status=status_code ) # 方案2:不指定pk,直接通过PUT请求创建新对象 else: obj = YourModel.objects.create(**request_data) return JsonResponse({"id": obj.id, "status": "created"}, status=201) except Exception as e: return JsonResponse({"error": str(e)}, status=400)
基于类的视图实现
from django.views import View from django.http import JsonResponse from .models import YourModel import json class PutCreateView(View): def put(self, request, pk=None): try: request_data = json.loads(request.body) if pk: obj, created = YourModel.objects.update_or_create(id=pk, defaults=request_data) else: obj = YourModel.objects.create(**request_data) created = True response_data = {"id": obj.id, **request_data} return JsonResponse(response_data, status=201 if created else 200) except Exception as e: return JsonResponse({"error": str(e)}, status=400)
核心思路就是手动解析PUT请求的body数据,然后调用Django的ORM方法(create或update_or_create)来完成对象创建。
2. 在Django Rest Framework中,当指定ID不存在对应对象时,如何使用PUT方法创建该ID对应的对象
DRF默认的UpdateAPIView或RetrieveUpdateAPIView在处理PUT请求时,如果指定的ID不存在,会直接返回404。要实现"不存在则创建"的逻辑,我们可以自定义视图来捕获异常,或者重写相关方法:
方法1:捕获DoesNotExist异常手动创建
from rest_framework import generics from rest_framework.response import Response from rest_framework import status from .models import YourModel from .serializers import YourModelSerializer class UpsertModelView(generics.GenericAPIView): queryset = YourModel.objects.all() serializer_class = YourModelSerializer def put(self, request, *args, **kwargs): pk = kwargs.get("pk") try: # 尝试获取对象,存在则更新 instance = self.get_object() serializer = self.get_serializer(instance, data=request.data) serializer.is_valid(raise_exception=True) self.perform_update(serializer) return Response(serializer.data, status=status.HTTP_200_OK) except YourModel.DoesNotExist: # 对象不存在时,用指定的ID创建新对象 create_data = request.data.copy() create_data["id"] = pk # 确保创建的对象ID为指定值 serializer = self.get_serializer(data=create_data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) return Response(serializer.data, status=status.HTTP_201_CREATED)
方法2:重写get_object方法实现自动创建
from rest_framework import generics from .models import YourModel from .serializers import YourModelSerializer class UpsertModelView(generics.UpdateAPIView): queryset = YourModel.objects.all() serializer_class = YourModelSerializer def get_object(self): pk = self.kwargs.get("pk") # 不存在则自动创建,存在则返回现有对象 obj, _ = YourModel.objects.get_or_create(id=pk) return obj
注意事项:
- 你的序列化器需要允许
id字段被写入:在YourModelSerializer中,不要将id设置为read_only=True,或者直接把id包含在fields列表中,否则无法在创建时指定ID。 - 方法2会在ID不存在时创建一个空对象(如果请求数据为空),如果需要避免这种情况,可以在
get_object或者perform_update里添加额外的校验逻辑。
内容的提问来源于stack exchange,提问作者Aashi
相关产品推荐
相关产品推荐

