Django Rest Framework Create REST API only for exe

2019-07-30 00:18发布

问题:

I'm working on a django project in which I need to build a rest API for some executions, I don't have much concerns about models as I only need to perform executions on the base of user's inputs/calls.

Here's my scenario:

  1. The Major thing is the Deployment ( An App in my project )

  2. On a get request user will get a list of all it's deployments(objects).

  3. A user will send a POST request to /deployments along with the complete object as:

    {
    "deployment_name": "dep4",
    "credentials": "cre4",
    "project_name": "pro4",
    "project_id": "004",
    "cluster_name": "clus4",
    "zone_region": "zon4",
    "services": "Single",
    "configuration": "conf4",
    "routing": "route4" }
    

    then I need to use this data, validate and perform some execution on the base of this data. For example, I will make deployments on a cloud platform with the help of this information by using third-party APIs.

I'm really confused by the documentation of DRF, especially about serializers.

Update: Currently, How I'm trying to do the POST: From apiview.py

class DeploymentsList(APIView):
    queryset = DeploymentOnUserModel.objects.all()

    def post(self, request):
        print(request.data)
        DeploymentOnUserModel.objects.create(
            deployment_name=request.data['deployment_name'],
            credentials=request.data['credentials'],
            project_name=request.data['project_name'],
            project_id=request.data['project_id'],
            cluster_name=request.data['cluster_name'],
            zone_region=request.data['zone_region'],
            services=request.data['services'],
            configuration=request.data['configuration'],
            routing=request.data['routing'],
        )
        return Response(request.data)

So, how can I validate the incoming data/request?

Here's my Deployment Model:

class DeploymentOnUserModel(models.Model):
    deployment_name = models.CharField(max_length=256, )
    credentials = models.TextField(blank=False)
    project_name = models.CharField(max_length=150, blank=False)
    project_id = models.CharField(max_length=150, blank=True)
    cluster_name = models.CharField(max_length=256, blank=False)
    zone_region = models.CharField(max_length=150, blank=False)
    services = models.CharField(max_length=150, choices=services)
    configuration = models.TextField()
    routing = models.TextField()

    def save(self, **kwargs):
        if not self.id and self.services == 'Multiple' and not self.routing and not self.configuration:
            raise ValidationError("You must have to provide routing for multiple services deployment.")
        super().save(**kwargs)

From urls.py:

app_name = 'deployments'

urlpatterns = [
    path('deployments/', apiview.DeploymentsList.as_view(), name='deployment_list'),
    path('deployments/<int:pk>', apiview.DeploymentDetail.as_view(), name='deployment_detail')

]

Which approach and things from DRF I should use to implement my API.

回答1:

You will probably want to implement DRFs ModelSerializer and ModelViewSet such that you can easily reuse the Django model you already have.

Your serializer could be like this (e.g. in serializers.py):

from rest_framework import serializers

from .models import DeploymentOnUser


class DeploymentOnUserModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = DeploymentOnUser
        fields = (deployment_name, credentials, )

You should add your own validation here, much like you would do with Django forms.

The viewset could be like this (e.g. in views.py):

from rest_framework import viewsets
from rest_framework.response import Response

from .models import DeploymentOnUserModel
from .serializers import DeploymentOnUserModelSerializer 


class DeploymentOnUserViewSet(viewsets.ModelViewSet):
    queryset = DeploymentOnUserModel.objects.all()
    serializer_class = DeploymentOnUserModelSerializer 

    def create(self, request, *args, **kwargs):
        """overwrite this for extra actions"""
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

Depending on your situation, you might even need to overwrite create -- this just shows how you could do it.

The ModelViewSet and ModelSerializer remove much of the boilerplate code. However, if you haven't used DRF before, it doesn't hurt to first go through the tutorial

Don't forget to also register the viewset in urls.py:

from django.conf.urls import url, include

from rest_framework import routers

from .views import DeploymentOnUserViewSet


router = routers.DefaultRouter()
router.register('deployments', DeploymentOnUserViewSet)

urlpatterns = [
    # other patterns also go here
    url('', include(router.urls)),
]

You could then test your API by doing e.g. a POST call on /deployments/.

For unit testing, I mostly use this pattern:

from rest_framework.test import APIRequestFactory

# Create a POST request, at the root
request = APIRequestFactory().post('/')
response = DeploymentOnUserViewSet.as_view({'post': 'create'})(request)
assert response.status_code == 200