Creating and retrieving related resources

Now, we will use the HTTPie command or its curl equivalents to compose and send HTTP requests to the API. We will use JSON for the requests that require additional data. Remember that you can perform the same tasks with your favorite GUI-based tool or with the browsable API.

First, we will compose and send an HTTP request to create a new game category. Remember that we used the browsable API to create a game category named '3D RPG'.

http POST :8000/game-categories/ name='2D mobile arcade'

The following is the equivalent curl command:

curl -iX POST -H "Content-Type: application/json" -d '{"name":"2D mobile arcade"}' :8000/game-categories/

The preceding command will compose and send a POST HTTP request with the specified JSON key-value pair. The request specifies /game-categories/, and therefore, it will match '^game-categories/$' and run the post method for the views.GameCategoryList class-based view. Remember that the method is defined in the ListCreateAPIView superclass and it ends up calling the create method defined in mixins.CreateModelMixin. If the new GameCategory instance was successfully persisted in the database, the call to the method will return an HTTP 201 Created status code and the recently persisted GameCategory serialized to JSON in the response body. The following line shows a sample response for the HTTP request with the new GameCategory object in the JSON response. The response doesn't include the header. Note that the response includes both the primary key, pk, and the url, url, for the created category. The games array is empty because there aren't games related to the new category yet:

{ 
    "games": [],  
    "name": "2D mobile arcade",  
    "pk": 4,  
    "url": "http://localhost:8000/game-categories/4/" 
} 

Now, we will compose and send HTTP requests to create two games that belong to the first category we recently created: 3D RPG. We will specify the game_category value with the name of the desired game category. However, the database table that persists the Game model will save the value of the primary key of the related GameCategory whose name value matches the one we provide:

http POST :8000/games/ name='PvZ Garden Warfare 4' game_category='3D RPG' played=false release_date='2016-06-21T03:02:00.776594Z'
http POST :8000/games/ name='Superman vs Aquaman' game_category='3D RPG' played=false release_date='2016-06-21T03:02:00.776594Z'

The following are the equivalent curl commands:

curl -iX POST -H "Content-Type: application/json" -d '{"name":"PvZ Garden Warfare 4", "game_category":"3D RPG", "played": "false", "release_date": "2016-06-21T03:02:00.776594Z"}' :8000/games/
curl -iX POST -H "Content-Type: application/json" -d '{"name":" Superman vs Aquaman", "game_category":"3D RPG", "played": "false", "release_date": "2016-06-21T03:02:00.776594Z"}' :8000/games/

The previous commands will compose and send two POST HTTP requests with the specified JSON key-value pairs. The request specifies /games/, and therefore, it will match '^games/$' and run the post method for the views.GameList class-based view. The following lines show sample responses for the two HTTP requests with the new Game objects in the JSON responses. The responses don't include the headers. Note that the response includes only the url, url, for the created games and doesn't include the primary key. The value for game_category is the name for the related GameCategory:

{ 
    "game_category": "3D RPG",  
    "name": "PvZ Garden Warfare 4",  
    "played": false,  
    "release_date": "2016-06-21T03:02:00.776594Z",  
    "url": "http://localhost:8000/games/2/" 
} 
{ 
    "game_category": "3D RPG",  
    "name": "Superman vs Aquaman",  
    "played": false,  
    "release_date": "2016-06-21T03:02:00.776594Z",  
    "url": "http://localhost:8000/games/3/" 
} 

We can run the previously explained commands to check the contents of the tables that Django created in the PostgreSQL database. We will notice that the game_category_id column for the games_game table saves the value of the primary key of the related row in the games_game_category table. The GameSerializer class uses the SlugRelatedField to display the name value for the related GameCategory. The following screenshot shows the contents of the games_game_category and the games_game table in a PostgreSQL database after running the HTTP requests:

Creating and retrieving related resources

Now, we will compose and send an HTTP request to retrieve the game category that is contains two games, that is the game category resource whose id or primary key is equal to 3. Don't forget to replace 3 with the primary key value of the game whose name is equal to '3D RPG' in your configuration:

http :8000/game-categories/3/

The following is the equivalent curl command:

curl -iX GET :8000/game-categories/3/

The previous commands will compose and send the following HTTP request: GET http://localhost:8000/game-categories/3/. The request has a number after /game-categories/, and therefore, it will match '^game-categories/(?P<pk>[0-9]+)/$' and run the get method for the views.GameCategoryDetail class based view. Remember that the method is defined in the RetrieveUpdateDestroyAPIView superclass and it ends up calling the retrieve method defined in mixins.RetrieveModelMixin. The following lines show a sample response for the HTTP request, with the GameCategory object and the hyperlinks of the related games in the JSON response:

HTTP/1.0 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Date: Tue, 21 Jun 2016 23:32:04 GMT
Server: WSGIServer/0.2 CPython/3.5.1
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN
{
    "games": [
        "http://localhost:8000/games/2/", 
        "http://localhost:8000/games/3/"
    ], 
    "name": "3D RPG", 
    "pk": 3, 
    "url": "http://localhost:8000/game-categories/3/"
}

The GameCategorySerializer class defined the games attribute as a HyperlinkedRelatedField, and therefore, the serializer renders the URL for each related Game instance in the value for the games array. If we view the results in a web browser through the browsable API, we will be able to click or tap on the hyperlink to see the details for each game.

Now, we will compose and send a POST HTTP request to create a game related to a game category name that doesn't exist: 'Virtual reality':

http POST :8000/games/ name='Captain America vs Thor' game_category='Virtual reality' played=false release_date='2016-06-21T03:02:00.776594Z'

The following is the equivalent curl command:

curl -iX POST -H "Content-Type: application/json" -d '{"name":"'Captain America vs Thor", "game_category":"Virtual reality", "played": "false", "release_date": "2016-06-21T03:02:00.776594Z"}' :8000/games/

Django won't be able to retrieve a GameCategory instance whose name is equal to the specified value, and therefore, we will receive a 400 Bad Request status code in the response header and a message related to the value specified in for game_category in the JSON body. The following lines show a sample response:

HTTP/1.0 400 Bad Request
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Date: Tue, 21 Jun 2016 23:51:19 GMT
Server: WSGIServer/0.2 CPython/3.5.1
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN
{
    "game_category": [
        "Object with name=Virtual reality does not exist."
    ]
}

Now, we will compose and send HTTP requests to create two players:

http POST :8000/players/ name='Brandon' gender='M'
http POST :8000/players/ name='Kevin' gender='M'

The following are the equivalent curl commands:

curl -iX POST -H "Content-Type: application/json" -d '{"name":"Brandon", "gender":"M"}' :8000/players/
curl -iX POST -H "Content-Type: application/json" -d '{"name":" Kevin", "gender":"M"}' :8000/players/

The previous commands will compose and send two POST HTTP requests with the specified JSON key-value pairs. The request specifies /players/, and therefore, it will match '^players/$' and run the post method for the views.PlayerList class based view. The following lines show sample responses for the two HTTP requests with the new Player objects in the JSON responses. The responses don't include the headers. Notice that the response includes only the url, url, for the created players and doesn't include the primary key. The value for gender_description is the choice description for the gender char. The scores array is empty because there aren't scores related to each new player yet:

{ 
    "gender": "M",  
    "name": "Brandon",  
    "scores": [],  
    "url": "http://localhost:8000/players/2/" 
} 
{ 
    "gender": "M",  
    "name": "Kevin",  
    "scores": [],  
    "url": "http://localhost:8000/players/3/" 
} 

Now, we will compose and send HTTP requests to create four scores:

http POST :8000/player-scores/ score=35000 score_date='2016-06-21T03:02:00.776594Z' player='Brandon' game='PvZ Garden Warfare 4'
http POST :8000/player-scores/ score=85125 score_date='2016-06-22T01:02:00.776594Z' player='Brandon' game='PvZ Garden Warfare 4'
http POST :8000/player-scores/ score=123200 score_date='2016-06-22T03:02:00.776594Z' player='Kevin' game='Superman vs Aquaman'
http POST :8000/player-scores/ score=11200 score_date='2016-06-22T05:02:00.776594Z' player='Kevin' game='PvZ Garden Warfare 4'

The following are the equivalent curl commands:

curl -iX POST -H "Content-Type: application/json" -d '{"score":"35000", "score_date":"2016-06-21T03:02:00.776594Z", "player":"Brandon", "game":"PvZ Garden Warfare 4"}' :8000/player-scores/
curl -iX POST -H "Content-Type: application/json" -d '{"score":"85125", "score_date":"2016-06-22T01:02:00.776594Z", "player":"Brandon", "game":"PvZ Garden Warfare 4"}' :8000/player-scores/
curl -iX POST -H "Content-Type: application/json" -d '{"score":"123200", "score_date":"2016-06-22T03:02:00.776594Z", "player":"Kevin", "game":"'Superman vs Aquaman"}' :8000/player-scores/
curl -iX POST -H "Content-Type: application/json" -d '{"score":"11200", "score_date":"2016-06-22T05:02:00.776594Z", "player":"Kevin", "game":"PvZ Garden Warfare 4"}' :8000/player-scores/

The previous commands will compose and send four POST HTTP requests with the specified JSON key-value pairs. The request specifies /player-scores/, and therefore, it will match '^player-scores/$' and run the post method for the views.PlayerScoreList class based view. The following lines show sample responses for the four HTTP requests with the new Player objects in the JSON responses. The responses don't include the headers.

Django REST Framework uses the PlayerScoreSerializer class to generate the JSON response. Thus, the value for game is the name for the related Game instance and the value for player is the name for the related Player instance. The PlayerScoreSerializer class used SlugRelatedField for both fields:

{ 
    "game": "PvZ Garden Warfare 4",  
    "pk": 3,  
    "player": "Brandon",  
    "score": 35000,  
    "score_date": "2016-06-21T03:02:00.776594Z",  
    "url": "http://localhost:8000/player-scores/3/" 
} 
{ 
    "game": "PvZ Garden Warfare 4",  
    "pk": 4,  
    "player": "Brandon",  
    "score": 85125,  
    "score_date": "2016-06-22T01:02:00.776594Z",  
    "url": "http://localhost:8000/player-scores/4/" 
} 
{ 
    "game": "Superman vs Aquaman",  
    "pk": 5,  
    "player": "Kevin",  
    "score": 123200,  
    "score_date": "2016-06-22T03:02:00.776594Z",  
    "url": "http://localhost:8000/player-scores/5/" 
} 
{ 
    "game": "PvZ Garden Warfare 4",  
    "pk": 6,  
    "player": "Kevin",  
    "score": 11200,  
    "score_date": "2016-06-22T05:02:00.776594Z",  
    "url": "http://localhost:8000/player-scores/6/" 
} 

We can run the previously explained commands to check the contents of the tables that Django created in the PostgreSQL database. We will notice that the game_id column for the games_playerscore table saves the value of the primary key of the related row in the games_game table. In addition, the player_id column for the games_playerscore table saves the value of the primary key of the related row in the games_player table. The following screenshot shows the contents for the games_game_category, games_game, games_player and games_playerscore tables in a PostgreSQL database after running the HTTP requests:

Creating and retrieving related resources

Now, we will compose and send an HTTP request to retrieve a specific player that contains two scores, which is the player resource whose id or primary key is equal to 3. Don't forget to replace 3 with the primary key value of the player whose name is equal to 'Kevin' in your configuration:

http :8000/players/3/

The following is the equivalent curl command:

curl -iX GET :8000/players/3/

The previous commands will compose and send the following HTTP request: GET http://localhost:8000/players/3/. The request has a number after /players/, and therefore, it will match '^players/(?P<pk>[0-9]+)/$' and run the get method for the views.PlayerDetail class based view. Remember that the method is defined in the RetrieveUpdateDestroyAPIView superclass and it ends up calling the retrieve method defined in mixins.RetrieveModelMixin. The following lines show a sample response for the HTTP request, with the Player object, the related PlayerScore objects and the Game object related to each PlayerScore object in the JSON response:

HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
    "url": "http://localhost:8000/players/3/",
    "name": "Kevin",
    "gender": "M",
    "gender_description": "Male",
    "scores": [
        {
            "url": "http://localhost:8000/player-scores/5/",
            "pk": 5,
            "score": 123200,
            "score_date": "2016-06-22T03:02:00.776594Z",
            "game": {
                "url": "http://localhost:8000/games/3/",
                "game_category": "3D RPG",
                "name": "Superman vs Aquaman",
                "release_date": "2016-06-21T03:02:00.776594Z",
                "played": false
            }
        },
        {
            "url": "http://localhost:8000/player-scores/6/",
            "pk": 6,
            "score": 11200,
            "score_date": "2016-06-22T05:02:00.776594Z",
            "game": {
                "url": "http://localhost:8000/games/2/",
                "game_category": "3D RPG",
                "name": "PvZ Garden Warfare 4",
                "release_date": "2016-06-21T03:02:00.776594Z",
                "played": false
            }
        }
    ]
}

The PlayerSerializer class defined the scores attribute as a ScoreSerializer with many equal to True, and therefore, this serializer renders each score related to the player. The ScoreSerializer class defined the game attribute as a GameSerializer, and therefore, this serializer renders each game related to the score. If we view the results in a web browser through the browsable API, we will be able to click or tap on the hyperlink of each of the related resources. However, in this case, we also see all their details without having to follow the hyperlink.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.218.157