在相同的Api视图中更新和删除,而不在Url中传递id

时间:2018-05-06 06:05:01

标签: python django django-rest-framework

如何在django rest框架中的一个URL端点执行crud操作?

目前我有2个url端点

url(r'^recipient/$', views.RecipientView.as_view()), # in this APiview im performing get all and post
url(r'^recipient/(?P<pk>[0-9]+)/$', views.RecipientDetail.as_view()), # in this APiview im performing retrieve, update delete.

现在要求是我删除第二个网址并在第一个api视图中执行所有操作?

我是django框架的新手可以有人帮我实现这个目标吗?

以下是我的代码。

View.py

class RecipientView(APIView):

     def get(self, request, format=None):
         Recipients = Recipient.objects.all()
         serializer = RecipientSerializer(Recipients, many=True)
         return Response(serializer.data)

     def post(self, request, format=None):
         serializer = RecipientSerializer(data=request.data)
         if serializer.is_valid():
             serializer.save()
             return Response(serializer.data, status=status.HTTP_201_CREATED)
         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


"""
class RecipientDetail(APIView):


    def get_object(self, pk):
        try:
            return Recipient.objects.get(pk=pk)
        except Recipient.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        Recipient = self.get_object(pk)
        serializer = RecipientSerializer(Recipient)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        Recipient = self.get_object(pk)
        serializer = RecipientSerializer(Recipient, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        Recipient = self.get_object(pk)
        Recipient.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
"""

model.py

class Recipient(models.Model):
    recipient = models.CharField(max_length=32, blank=False, null=False)
    def __str__(self):
        """returns the model as string."""
        return self.racipi

耳鼻喉科

serializer.py

class RecipientSerializer(serializers.ModelSerializer):

    class Meta:
        model = Recipient
        fields = '__all__'

我无法在同一视图中更新和删除,需要帮助吗?

3 个答案:

答案 0 :(得分:0)

您的第二个URL正在接收一个参数,可用于从数据库中获取数据对象,然后对该特定实例执行任何操作。如果您看到类RecipientDetail,则会看到所有方法都接受名为pk的参数,该参数与您要从数据库中提取的对象相关。

但您的第一个网址适用于Create New ObjectList All Objects等通用操作,并且使用这些端点执行特定于实例的操作并不好。

您可以阅读有关REST API标准enpoints的更多信息,以了解详细信息。以下是参考链接:

https://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

答案 1 :(得分:0)

您可以避免使用POST请求在URL中传递ID。提供ID和某种&#34;动作&#34;动词,例如请求正文中的action=delete

这不被认为是RESTful,部分原因是HTTP DELETE和PUT动词完美地描述了所请求的操作,但也因为POST被认为是非幂等方法,这意味着服务器状态将随着每个成功的请求而改变。作为幂等,重复的DELETE / PUT(以及GET)请求将使服务器处于相同的状态。

拥有第二条路径以及实现REST API的观点并不是一件很麻烦的事情,因此最好保持原样。

答案 2 :(得分:0)

最简单的方法是使用DRF的ViewSet。它已经为您提供了基本的CRUD操作,因此您可以使用以下内容创建视图:

# views.py
from rest_framework import viewsets

from .models import Recipient
from .serializers import RecipientSerializer


class RecipientViewSet(viewsets.ModelViewSet):
    """
    A viewset for viewing and editing recipient instances.
    """
    serializer_class = RecipientSerializer
    queryset = Recipient.objects.all()

由于我们使用的是ModelViewSet,它已经提供了get,list,update等操作,正如您在documentation中看到的那样。

然后,您可以在urls.py中使用routers,如下所示:

# urls.py
from rest_framework.routers import DefaultRouter

from myapp.views import RecipientViewSet

router = DefaultRouter()
router.register(r'recipients', RecipientViewSet)
urlpatterns = router.urls

上面的网址会生成一个网址,就像你在问题中写的那样:

# Add recipient
POST /recipients/

# Get list of recipients
GET /recipients/

# Get recipient detail
GET /recipients/:recipient_id/

# Update recipient
PUT/PATCH /recipients/:recipient_id/

# Delete recipient
DELETE /recipients/:recipient_id/

请注意,这是一个简化版本,您甚至可以使用指定的操作创建自己的网址模式。

<强>更新

感谢mhawke的澄清。正如mhawke在评论中所说,这可能不是OP想要的,如果你只是想避免在网址中传递ID,那么你可以按照mawke的回答,是的,它不被认为是RESTful。