You just need to remove the browsable API renderer from your list of supported renderers for the view.
Generally:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
)
}
Per-view basis:
class MyView(...):
renderer_classes = [renderers.JSONRenderer]
Aside:
In many cases I think it's a shame that folks would choose to disable the browsable API in any case, as it's a big aid to any developers working on the API, and it doesn't give them more permissions that they would otherwise have. I can see that there might be business reasons for doing so in some cases, but generally I'd consider it a huge asset. Although, in some cases there may be details shown (like the names of custom actions) that a non-public API may not want to expose.
See also the answer below for more detail about restricting the browsable API renderer to development.
Django-rest-framework works well even without tying it to a model. Your approach sounds ok, but I believe you can trim some of the steps to get everything working.
For example, rest framework comes with a few built-in renderers. Out of the box it can return JSON and XML to the API consumer. You can also enable YAML by just installing the required python module. Django-rest-framework will output any basic object like dict, list and tuple without any extra work on your part.
So basically you only have to create the function or class that takes in arguments, does all of the required calculations and returns its results in a tuple to the REST api view. If JSON and/or XML fits your needs, django-rest-framework will take care of the serialization for you.
You can skip steps 2 and 3 in this case, and just use one class for calculations and one for presentation to the API consumer.
Here are a few snippets may help you out:
Please note that I have not tested this. It's only meant as an example, but it should work :)
The CalcClass:
class CalcClass(object):
def __init__(self, *args, **kw):
# Initialize any variables you need from the input you get
pass
def do_work(self):
# Do some calculations here
# returns a tuple ((1,2,3, ), (4,5,6,))
result = ((1,2,3, ), (4,5,6,)) # final result
return result
The REST view:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from MyProject.MyApp import CalcClass
class MyRESTView(APIView):
def get(self, request, *args, **kw):
# Process any get params that you may need
# If you don't need to process get params,
# you can skip this part
get_arg1 = request.GET.get('arg1', None)
get_arg2 = request.GET.get('arg2', None)
# Any URL parameters get passed in **kw
myClass = CalcClass(get_arg1, get_arg2, *args, **kw)
result = myClass.do_work()
response = Response(result, status=status.HTTP_200_OK)
return response
Your urls.py:
from MyProject.MyApp.views import MyRESTView
from django.conf.urls.defaults import *
urlpatterns = patterns('',
# this URL passes resource_id in **kw to MyRESTView
url(r'^api/v1.0/resource/(?P<resource_id>\d+)[/]?$', login_required(MyRESTView.as_view()), name='my_rest_view'),
url(r'^api/v1.0/resource[/]?$', login_required(MyRESTView.as_view()), name='my_rest_view'),
)
This code should output a list of lists when you access http://example.com/api/v1.0/resource/?format=json. If using a suffix, you can substitute ?format=json
with .json
. You may also specify the encoding you wish to get back by adding "Content-type"
or "Accept"
to the headers.
[
[
1,
2,
3
],
[
4,
5,
6
]
]
Hope this helps you out.
Best Answer
@list_route
and@detail_route
are extra actions that we can add to aViewSet
. Both provide a custom routing facility in view set. Any methods on theViewSet
decorated with@detail_route
or@list_route
will also be routed.list_route
will give all the related records, whereasdetail_route
will provide only a particular record. For example, given a method like this on the UserViewSet class:The following URL pattern would additionally be generated:
For more information on routers you can visit the official Django Rest Rramewrok documentation on routers.
If you want get
xxx/books/1/
then yoururl.py
andviews.py
should look like this.urls.py
:views.py
: