3

I need to do an api to make some kind of logic (e.g: process some data, generate a wordcloud, make a ml layer...) and return a simple status. In the logic that I want to do, i don't need a model, just only receive a json with some parameters and do what i want to do.

I just already created the api view, but i can't find the way to receive parameters in the body.

I was reading about a good pattern to design my method (Django Rest Framework Business Logic, Separation of business logic and data access in django) and I wrote my code in the api.py file. I'm not using a serializer for this view, because I don't need to consume data from a model, instead of that, i use the input json.

api.py

from rest_framework import viewsets
from rest_framework import views
from rest_framework import status
from rest_framework.response import Response
from rest_framework_swagger.views import get_swagger_view

class WordCloudViewSet(viewsets.ViewSet):

    def create(self, request, *args, **kwargs):
        comments_list = kwargs['data']['comments']
        user_id = kwargs['data']['user_id']
        '''
        some logic
        '''
        return Response(status=status.HTTP_200_OK)

urls.py

from django.conf.urls import include, url
from rest_framework import routers
from .api import (WordCloudViewSet)
from api import views

router = routers.DefaultRouter()

schema_view = get_swagger_view(title='Swagger Documentation')

urlpatterns = [
    url(r'^api/wordcloud/', WordCloudViewSet.as_view({'get': 'list', 'post':'create'}), name='wordcloud')
]

urlpatterns += router.urls

I tried sending a json by body in postman like:

{
    "data": {
        "comments": ["Lorem ipsum dolor sit amet"],
        "user_id": 1
    }
}

But args and kwargs comes empty. Even in the swagger UI, I can't see parameters label to send my json.

enter image description here

All examples that I found, use model and serializers.

A simple Api View that receive a and return a "Hello" + Name, will be enough for me.

How can I specified in WordCloudViewSet, input parameters via post request, without use a model?

Thank you for looking, and thanks in advance for responding.

Edit

Surprisingly, i hadn't tried with request.data and it works. However, in swagger UI i can't test my api as I comment previosluy, because it's not displaying an input label to send the request.

Manuel Carrero
  • 599
  • 1
  • 9
  • 29

1 Answers1

-1

At the end, I found a simple solution, I just had to change the url, from this:

urlpatterns = [
    url(r'^api/wordcloud/', WordCloudViewSet.as_view({'get': 'list', 'post':'create'}), name='wordcloud')
]

To this:

urlpatterns = [
    url(r'^api/wordcloud/comments/<string:comments>/user_id/<int:user_id>', WordCloudViewSet.as_view({'get': 'list', 'post':'create'}), name='wordcloud')
]

Then In swagger it display the labels for the parameters: enter image description here

Aditional information another suggestion for any other person with the same problem is that I preferred to use a serializer even if I did not need to consume data from a Model, only for required and optionals parameters validation:

In serializers.py

class WordCloudAPISerializer(serializers.ModelSerializer):
    comments = serializers.CharField(required=True)
    user = serializers.IntegerField(source='id',required=False)
    class Meta:
        model = User
        fields = ('comments','user')

    def to_internal_value(self, data):
        required = []
        optionals = []
        for k in ['comments']:
            '''
            - Case 1: Is the k field in the data and it's empty?
            - Case 2: Is not the k field in the data?
            '''
            if (data.keys().__contains__(k) and data[k] == '') or (not data.keys().__contains__(k)):
                required.append(k)

        for k in ['user']:
            # Is not the k field in the data?
            if not data.keys().__contains__(k):
                optionals.append(k)

        if len(required) > 0 and len(optionals) > 0:
            raise ValueError("The following fields are required: %s" % ','.join(required) + " and the following fields are needed but can be empty: %s" % ','.join(optionals))

        elif len(required) > 0 and len(optionals) == 0:
            raise ValueError("The following fields are required: %s" % ','.join(required))

        elif len(required) == 0 and len(optionals) > 0:
            raise ValueError("The following fields are needed but can be empty: %s" % ','.join(optionals))

        return data

Then in api.py

            serializer = WordCloudAPISerializer(data=kwargs['data'])
            if serializer.is_valid():
                '''some logic'''
            else:
                return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)

I hope this could be useful for anyone else.

Manuel Carrero
  • 599
  • 1
  • 9
  • 29