Reader small image

You're reading from  Building RESTful Python Web Services

Product typeBook
Published inOct 2016
Reading LevelIntermediate
PublisherPackt
ISBN-139781786462251
Edition1st Edition
Languages
Concepts
Right arrow
Author (1)
Gaston C. Hillar
Gaston C. Hillar
author image
Gaston C. Hillar

Gaston C. Hillar is Italian and has been working with computers since he was 8 years old. Gaston has a Bachelor's degree in computer science (graduated with honors) and an MBA. Currently, Gaston is an independent IT consultant and a freelance author who is always looking for new adventures anywhere in the world. He was a senior contributing editor at Dr. Dobb's, and has written more than a hundred articles on software development topics. He has received the prestigious Intel Black Belt Software Developer award eight times. He has written many articles about Java for Oracle Java Magazine. Gaston was also a former Microsoft MVP in technical computing. He lives with his wife, Vanesa, and his two sons, Kevin and Brandon.
Read more about Gaston C. Hillar

Right arrow

Chapter 2.  Working with Class-Based Views and Hyperlinked APIs in Django

In this chapter, we will expand the capabilities of the RESTful API that we started in the previous chapter. We will change the ORM settings to work with a more powerful PostgreSQL database and we will take advantage of the advanced features included in Django REST Framework that allow us to reduce the boilerplate code for complex APIs, such as class-based views. We will:

  • Use model serializers to eliminate duplicate code

  • Work with wrappers to write API views

  • Use the default parsing and rendering options and move beyond JSON

  • Browse the API

  • Design a RESTful API to interact with a complex PostgreSQL database

  • Understand the tasks performed by each HTTP method

  • Declare relationships with the models

  • Manage serialization and deserialization with relationships and hyperlinks

  • Create class based views and use generic classes

  • Work with endpoints for the API

  • Create and retrieve related resources

Using model serializers to eliminate duplicate code


The GameSerializer class declares many attributes with the same names that we used in the Game model and repeats information, such as the types and the max_length values. The GameSerializer class is a subclass of rest_framework.serializers.Serializer, it declares attributes that we manually mapped to the appropriate types and overrides the create and update methods.

Now, we will create a new version of the GameSerializer class that will inherit from the rest_framework.serializers.ModelSerializer class. The ModelSerializer class automatically populates both set of default fields and a set of default validators. In addition, the class provides default implementations for the create and update methods.

Tip

In case you have any experience with Django Web Framework, you will notice that the Serializer and ModelSerializer classes are similar to the Form and ModelForm classes.

Now, go to the gamesapi/games folder and open the serializers.py file....

Working with wrappers to write API views


Our code in the games/views.py file declared a JSONResponse class and two function-based views. These functions returned JSONResponse when it was necessary to return JSON data and a django.Http.Response.HttpResponse instance when the response was just of an HTTP status code.

No matter the accepted content type specified in the HTTP request header, the view functions always provide the same content in the response body-JSON. Run the following two commands to retrieve all the games with different values for the Accept request header-text/html and application/json :

http :8000/games/ Accept:text/html
http :8000/games/ Accept:application/json

The following are the equivalent curl commands:

curl -H 'Accept: text/html' -iX GET :8000/games/
curl -H 'Accept: application/json' -iX GET :8000/games/

The preceding commands will compose and send the following HTTP request: GET http://localhost:8000/games/. The first command defines the text/html value for the Accept...

Using the default parsing and rendering options and move beyond JSON


The APIView class specifies default settings for each view that we can override by specifying appropriate values in the gamesapi/settings.py file or by overriding the class attributes in subclasses. As previously explained, the usage of the APIView class under the hoods makes the decorator apply these default settings. Thus, whenever we use the decorator, the default parser classes and the default renderer classes will be associated with the function views.

By default, the value for the DEFAULT_PARSER_CLASSES is the following tuple of classes:

( 
    'rest_framework.parsers.JSONParser', 
    'rest_framework.parsers.FormParser', 
    'rest_framework.parsers.MultiPartParser' 
) 

When we use the decorator, the API will be able to handle any of the following content types through the appropriate parsers when accessing the request.data attribute:

  • application/json

  • application/x-www-form-urlencoded

  • multipart/form-data

Tip

When...

Browsing the API


With the recent edits, we made it possible for our API to use the default content renderers configured in Django REST Framework, and therefore, our API is capable of rendering the text/html content. We can take advantage of the browsable API, a feature included in Django REST Framework that generates human-friendly HTML output for each resource whenever the request specifies text/html as the value for the Content-type key in the request header.

Whenever we enter a URL for an API resource in a web browser, the browser will require an HTML response, and therefore, Django REST Framework will provide an HTML response built with Bootstrap (http://getbootstrap.com). This response will include a section that displays the resource content in JSON, buttons to perform different requests, and forms to submit data to the resources. As everything in Django REST Framework, we can customize the templates and themes used to generate the browsable API.

Open a web browser and enter http://localhost...

Designing a RESTful API to interact with a complex PostgreSQL database


So far, our RESTful API has performed CRUD operations on a single database table. Now, we want to create a more complex RESTful API with Django REST Framework to interact with a complex database model that has to allow us to register player scores for played games that are grouped into game categories. In our previous RESTful API, we used a string field to specify the game category for a game. In this case, we want to be able to easily retrieve all the games that belong to a specific game category, and therefore, we will have a relationship between a game and a game category.

We should be able to perform CRUD operations on different related resources and resource collections. The following list enumerates the resources and the model names that we will use to represent them in Django REST Framework:

  • Game categories (GameCategory model)

  • Games (Game model)

  • Players (Player model)

  • Player scores (PlayerScore model)

The game category...

Understanding the tasks performed by each HTTP method


The following table shows the HTTP verbs, the scope, and the semantics for the methods that our new API must support. Each method is composed by an HTTP verb and a scope and all the methods have well-defined meanings for all the resources and collections.

Declaring relationships with the models


Make sure you quit the Django's development server. Remember that you just need to press Ctrl + C in the terminal or command-prompt window in which it is running. Now, we will create the models that we are going to use to represent and persist the game categories, games, players and scores, and their relationships. Open the games/models.py file and replace its contents with the following code. The lines that declare fields related to other models are highlighted in the code listing. The code file for the sample is included in the restful_python_chapter_02_03 folder.

from django.db import models 
 
 
class GameCategory(models.Model): 
    name = models.CharField(max_length=200) 
 
    class Meta: 
        ordering = ('name',) 
 
    def __str__(self): 
        return self.name 
 
 
class Game(models.Model): 
    created = models.DateTimeField(auto_now_add=True) 
    name = models.CharField(max_length=200) 
    game_category = models.ForeignKey( ...

Creating class-based views and using generic classes


This time, we will write our API views by declaring class-based views, instead of function-based views. We might code classes that inherit from the rest_framework.views.APIView class and declare methods with the same names than the HTTP verbs we want to process: get, post, put, patch, delete, and so on. These methods receive a request argument as happened with the functions that we created for the views. However, this approach would require us to write a lot of code. Instead, we can take advantage of a set of generic views that we can use as our base classes for our class-based views to reduce the required code to the minimum and take advantage of the behavior that has been generalized in Django REST Framework.

We will create subclasses of the two following generic class views declared in rest_framework.generics:

  • ListCreateAPIView: Implements the get method that retrieves a listing of a queryset and the post method that creates a model...

Taking advantage of generic class based views


Go to the gamesapi/games folder and open the views.py file. Replace the code in this file with the following code that declares the required imports and the class based views. We will add more classes to this file later. The code file for the sample is included in the restful_python_chapter_02_03 folder:

from games.models import GameCategory 
from games.models import Game 
from games.models import Player 
from games.models import PlayerScore 
from games.serializers import GameCategorySerializer 
from games.serializers import GameSerializer 
from games.serializers import PlayerSerializer 
from games.serializers import PlayerScoreSerializer 
from rest_framework import generics 
from rest_framework.response import Response 
from rest_framework.reverse import reverse 
 
 
class GameCategoryList(generics.ListCreateAPIView): 
    queryset = GameCategory.objects.all() 
    serializer_class = GameCategorySerializer 
    name = 'gamecategory-list' 
 
...

Working with endpoints for the API


We want to create an endpoint for the root of our API to make it easier to browse the API with the browsable API feature and understand how everything works. Add the following code to the views.py file to declare the ApiRoot class. The code file for the sample is included in the restful_python_chapter_02_03 folder.

class ApiRoot(generics.GenericAPIView): 
    name = 'api-root' 
    def get(self, request, *args, **kwargs): 
        return Response({ 
            'players': reverse(PlayerList.name, request=request), 
            'game-categories': reverse(GameCategoryList.name, request=request), 
            'games': reverse(GameList.name, request=request), 
            'scores': reverse(PlayerScoreList.name, request=request) 
            }) 

The ApiRoot class is a subclass of the rest_framework.generics.GenericAPIView class and declares the get method. The GenericAPIView class is the base class for all the other generic views. The ApiRoot class defines the...

Test your knowledge


  1. Under the hoods, the @api_view decorator is:

    1. A wrapper that converts a function-based view into a subclass of the rest_framework.views.APIView class.

    2. A wrapper that converts a function-based view into a serializer.

    3. A wrapper that converts a function-based view into a subclass of the rest_framework.views.api_view class.

  2. The browsable API, a feature included in Django REST Framework that:

    1. Generates human-friendly JSON output for each resource whenever the request specifies application/json as the value for the Content-type key in the request header.

    2. Generates human-friendly HTML output for each resource whenever the request specifies text/html as the value for the Content-type key in the request header.

    3. Generates human-friendly HTML output for each resource whenever the request specifies application/json as the value for the Content-type key in the request header.

  3. The rest_framework.serializers.ModelSerializer class:

    1. Automatically populates both a set of default constraints...

Summary


In this chapter, we took advantage of the various features included in Django REST Framework that allowed us to eliminate duplicate code and build our API reusing generalized behaviors. We used model serializers, wrappers, default parsing, and rendering options, class based views, and generic classes.

We used the browsable API feature and we designed a RESTful API that interacted with a complex PostgreSQL database. We declared relationships with the models, managed serialization and deserialization with relationships, and hyperlinks. Finally, we created and retrieved related resources and we understood how things work under the hoods.

Now that we have built a complex API with Django REST Framework, we will use additional abstractions included in the framework to improve our API, we will add security and authentication, which is what we are going to discuss in the next chapter.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Building RESTful Python Web Services
Published in: Oct 2016Publisher: PacktISBN-13: 9781786462251
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Gaston C. Hillar

Gaston C. Hillar is Italian and has been working with computers since he was 8 years old. Gaston has a Bachelor's degree in computer science (graduated with honors) and an MBA. Currently, Gaston is an independent IT consultant and a freelance author who is always looking for new adventures anywhere in the world. He was a senior contributing editor at Dr. Dobb's, and has written more than a hundred articles on software development topics. He has received the prestigious Intel Black Belt Software Developer award eight times. He has written many articles about Java for Oracle Java Magazine. Gaston was also a former Microsoft MVP in technical computing. He lives with his wife, Vanesa, and his two sons, Kevin and Brandon.
Read more about Gaston C. Hillar

HTTP verb

Scope

Semantics

GET

Collection of game categories

Retrieve all the stored game categories in the collection, sorted by their name in ascending order. Each game category must include a list of URLs for each game resource that belongs to the category.

GET

Game category

Retrieve a single game category. The game category must include a list of URLs for each game resource that belongs to the category.

POST

Collection of game categories

Create a new game category in the collection.

PUT

Game category

Update an existing game category.

PATCH

Game category

Update one or more fields of an existing game category.

DELETE

Game category

Delete an existing...