Skip to content
thesarfo

Note

Creating API Views

Wrapping a plain Django view with @api_view to get DRF's Request/Response classes and a browsable API, plus URL converters for path parameters.

views 0
  1. First let’s revise on how to create a view. Now what we want to do is that, we want to create an endpoint called “/store/products” that will return all the products we have in our db. So first we need to create the view function

Inside your store app, open the views.py file and then create a simple view function that returns a response of “ok”. see below

from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def product_list(request):
return HttpResponse('ok')
  1. The next thing you need to do is to map the view function to a url pattern(inside the same app). so since the urls.py file doesnt exist in the store app. go ahead and create it. and then map your url to its view function.
from django.urls import path
from . import views
# URLConf
urlpatterns = [
path('products/', views.product_list)
]
  1. Now this url belongs to the store app. and we need to import it in our main url module(the one in our main app, the directory that contains the settings.py). So go inside your root urls.py file and then add the store urls to it.
from django.contrib import admin
from django.urls import path, include
import debug_toolbar
admin.site.site_header = "StoreFront Admin"
admin.site.index_title = "Admin"
urlpatterns = [
path('admin/', admin.site.urls),
path('playground/', include('playground.urls')),
path('store/', include('store.urls')),
path('__debug__/', include(debug_toolbar.urls)),
]
# What we're basically saying is that, if the url starts with "store/" we want it to be handled by the store.urls file.
  1. In django, we have two classes. the HttpRequest and HttpResponse, but the DRF also comes with its own Request and Response classes. And its much simpler than the one that comes with django. this is how to use them
from django.shortcuts import render
from django.http import HttpResponse
from rest_framework.decorators import api_view
@api_view()
def product_list(request):
return HttpResponse('ok')

Now first you import the api_view decorator from drf decorators, and you apply the decorator to the view function. When you apply the api_view() decorator to your view function, the request object that we receive in your product_list function will be an instance of the Request class of DRF. so this will replace the request object in django with the newer request object that comes with the django rest framework.

Similarly, you replace the old HttpResponse that comes in django with the newer one that comes in drf. Import Response from drf and return an instance of that Response

from django.shortcuts import render
from django.http import HttpResponse
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view()
def product_list(request):
return Response('ok')

Now with this two simple changes, when you hit your endpoint one more time, you will get a beautiful browsable api.

Challenge

Lets create another view function that displays the product detail based on the products id.

  • In your views.py file..do the below
from django.shortcuts import render
from django.http import HttpResponse
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view()
def product_list(request):
return Response('ok')
@api_view()
def product_detail(request, id):
'''note how we pass the id as a param to the function'''
return Response(id)
  • Now in your urls.py file
from django.urls import path
from . import views
# URLConf
urlpatterns = [
path('products/', views.product_list),
path('products/<id>/', views.product_detail)
]
# Notice how we are using the angle bracket to pass the id into the url
  • The thing is, now if we pass a letter to our url like this “http://127.0.0.1:8000/store/products/a/”, the url still works and it return the “a” as a response.

  • But we dont want it to be so, since our product ids can only be integers. So we add a convertor to our url pattern like so

path('products/<int:id>/', views.product_detail)