1

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.

4
  • Can you please elaborate as to what your query is so that we might be able to help? Commented Jun 27, 2018 at 11:40
  • Well, the question is: if you don't need DRF features and DRF actually gets in the way, why would you use DRF at all ? You don't need it to build a REST api with Django, you could just do it by hand (it's only requests and responses in the end) or use some lighter lib like toastdriven's restless. Commented Jun 27, 2018 at 11:55
  • Hi @brunodesthuilliers, I will need other things from drf like permissions, authentications etc. Commented Jun 27, 2018 at 12:00
  • Hi @MuhammadFahadManzoor, to implement my own get and posts like django views, should i use APIView? Commented Jun 27, 2018 at 12:01

1 Answer 1

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
Sign up to request clarification or add additional context in comments.

5 Comments

Hi @martyn! So, create will call when a post request comes?
Now it returns another error as: raise TypeError("The actions argument must be provided when " TypeError: The actions argument must be provided when calling .as_view() on a ViewSet. For example .as_view({'get': 'list'})
Yes, create should be the method linked to a post call. I did not mention this in my post, but you would also need to add a router (e.g. DefaultRouter ) to your urls.py, similar to how you would do this for a Django app
Now, it returns AttributeError: 'str' object has no attribute 'values'
I'm not doing any unit testing, and even I have added {'post': 'create'} in my url but still, this error occurs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.