Creating and retrieving related resources

Now we will use the HTTP 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 as your favorite GUI-based tool or with the browsable API.

First, we will run the following command to compose and send an HTTP POST request to create a new ESRB rating. Remember that we used the browsable API to create an ESRB rating with the following description: 'AO (Adults Only)'. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd615.txt file:

    http POST ":8000/esrb-ratings/" description='T (Teen)'
  

The following is the equivalent curl command. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd616.txt file:

    curl -iX POST -H "Content-Type: application/json" -d '{"description":"T (Teen)"}' "localhost:8000/esrb-ratings/"
  

The previous command will compose and send an HTTP POST request with the specified JSON key-value pair. The request specifies /esrb-ratings/, and therefore, it will match '^esrb-ratings/$' and run the post method for the views.EsrbRatingList 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 EsrbRating instance was successfully persisted in the database, the call to the method will return an HTTP 201 Created status code and the recently persisted EsrbRating serialized to JSON in the response body. The following line shows a sample response for the HTTP request with the new EsrbRating object in the JSON response.

The response doesn't include the header. Notice that the response includes both the id and the url, for the created ESRB rating. The games array is empty because there aren't games related to each new ESRB rating yet:

    {
        "description": "T (Teen)",
        "games": [],
        "id": 2,
        "url": "http://localhost:8000/esrb-ratings/2/"
    }
  

Now we will compose and send HTTP requests to create two games that belong to the first ESRB rating we created with the browsable API: AO (Adults Only). We will specify the esrb_rating value with the description of the desired ESRB rating. However, the database table that persists the Game model will save the value of the id of the related EsrbRating whose description value matches the one we provide. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd617.txt file:

    http POST ":8000/games/" name='Battlefield V' esrb_rating='AO (Adults Only)' release_date='2017-05-01T01:02:00.776594Z'
    http POST ":8000/games/" name='Mutant Football League: Dynasty Edition' esrb_rating='AO (Adults Only)' release_date='2018-10-20T03:02:00.776594Z'
  

The following are the equivalent curl commands. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd618.txt file:

    curl -iX POST -H "Content-Type: application/json" -d '{"name":"Battlefield V", "esrb_rating":"AO (Adults Only)", "release_date": "2017-05-01T01:02:00.776594Z"}' "localhost:8000/games/"
    curl -iX POST -H "Content-Type: application/json" -d '{"name":"Mutant Football League: Dynasty Edition", "esrb_rating":"AO (Adults Only)", "release_date": "2018-10-20T03:02:00.776594Z"}' "localhost:8000/games/"
  

The previous commands will compose and send two HTTP POST requests with the specified JSON key-value pairs. The requests specify /games/, and therefore, they 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. Notice that the response includes only the url for the created games and doesn't include the ID. The value for esrb_rating is the description for the related EsrbRating:

    {
        "esrb_rating": "AO (Adults Only)",
        "name": "Battlefield V",
        "played_once": false,
        "played_times": 0,
        "release_date": "2017-05-01T01:02:00.776594Z",
        "url": "http://localhost:8000/games/1/"
    }
    {
        "esrb_rating": "AO (Adults Only)",
        "name": "Mutant Football League: Dynasty Edition",
        "played_once": false,
        "played_times": 0,
        "release_date": "2018-10-20T03:02:00.776594Z",
        "url": "http://localhost:8000/games/2/"
    }
  

We can run the previously explained commands to check the contents of the tables that Django created after executing the migrations process in the PostgreSQL database. We will notice that the esrb_rating_id column for the games_game table saves the value of the id of the related row in the games_esrb_rating table. The GameSerializer class uses the SlugRelatedField to display the name value for the related EsrbRating. The following screenshot shows the contents for the games_esrb_rating and the games_game table in a PostgreSQL 10.5 database after running the HTTP requests:

Now we will compose and send an HTTP GET request to retrieve the ESRB rating that contains two games, that is, the ESRB rating resource whose id is equal to 1. Don't forget to replace 1 with the id value of the ESRB rating whose description is equal to 'AO (Adults Only)' in your configuration. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd619.txt file:

    http ":8000/esrb-ratings/1/"
  

The following is the equivalent curl command. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd620.txt file:

    curl -iX GET "localhost:8000/esrb-ratings/1/"
  

The previous commands will compose and send the following HTTP request: GET http://localhost:8000/esrb-ratings/1/. The request has a number after /esrb-ratings/, and therefore, it will match '^esrb-ratings/(?P<pk>[0-9]+)/$' and run the get method for the views.EsrbRatingDetail 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 EsrbRating object and the hyperlinks of the related games in the JSON response:

    HTTP/1.1 200 OK
    Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
    Content-Length: 163
    Content-Type: application/json
    Date: Fri, 26 Oct 2018 02:18:39 GMT
    Server: WSGIServer/0.2 CPython/3.7.1
    Vary: Accept, Cookie
    X-Frame-Options: SAMEORIGIN
    
    {
        "description": "AO (Adults Only)",
        "games": [
            "http://localhost:8000/games/1/",
            "http://localhost:8000/games/2/"
        ],
        "id": 1,
        "url": "http://localhost:8000/esrb-ratings/1/"
    }
  

The EsrbRatingSerializer 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 an HTTP POST request to create a game related to an ESRB rating name that doesn't exist: 'Virtual reality'. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd621.txt file:

    http POST ":8000/games/" name='LEGO DC Super-Villains' esrb_rating='EC (Early Childhood)' release_date='2018-01-10T03:02:00.776594Z'
  

The following is the equivalent curl command. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd622.txt file:

    curl -iX POST -H "Content-Type: application/json" -d '{"name":"LEGO DC Super-Villains", "esrb_rating":"EC (Early Childhood)", "release_date": "2018-01-10T03:02:00.776594Z"}' "localhost:8000/games/"
  

Django won't be able to retrieve an EsrbRating instance whose description 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 esrb_rating in the JSON body. The following lines show a sample response:

    HTTP/1.1 400 Bad Request
    Allow: GET, POST, HEAD, OPTIONS
    Content-Length: 80
    Content-Type: application/json
    Date: Fri, 26 Oct 2018 02:42:07 GMT
    Server: WSGIServer/0.2 CPython/3.7.1
    Vary: Accept, Cookie
    X-Frame-Options: SAMEORIGIN
    
    {
        "esrb_rating": [
            "Object with description=EC (Early Childhood) does not exist."
        ]
    }
  

Now we will compose and send two HTTP POST requests to create two players. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd623.txt file:

    http POST ":8000/players/" name='Gaston Hillar' gender='M'
    http POST ":8000/players/" name='Enzo Scocco' gender='M'
  

The following are the equivalent curl commands. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd624.txt file:

    curl -iX POST -H "Content-Type: application/json" -d '{"name":"Gaston Hillar", "gender":"M"}' "localhost:8000/players/"
    curl -iX POST -H "Content-Type: application/json" -d '{"name":"Enzo Scocco", "gender":"M"}' "localhost:8000/players/"
  

The previous commands will compose and send two HTTP POST 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 each response includes only the url for the created players and doesn't include the id. 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",
        "gender_description": "Male",
        "name": "Gaston Hillar",
        "scores": [],
        "url": "http://localhost:8000/players/1/"
    }
    {
        "url":"http://localhost:8000/players/2/",
        "name":"Enzo Scocco",
        "gender":"M",
        "gender_description":"Male",
        "scores":[]
    }
  

Now we will compose and send HTTP requests to create four scores. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd625.txt file:

    http POST ":8000/player-scores/" score=17500 score_date='2019-01-01T03:02:00.776594Z' player='Gaston Hillar' game='Battlefield V'
    http POST ":8000/player-scores/" score=3225 score_date='2019-01-01T01:02:00.776594Z' player='Gaston Hillar' game='Mutant Football League: Dynasty Edition'
    http POST ":8000/player-scores/" score=43200 score_date='2019-01-01T03:02:00.776594Z' player='Enzo Scocco' game='Battlefield V'
    http POST ":8000/player-scores/" score=17420 score_date='2019-01-01T05:02:00.776594Z' player='Enzo Scocco' game='Mutant Football League: Dynasty Edition'
  

The following are the equivalent curl commands. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd626.txt file:

    curl -iX POST -H "Content-Type: application/json" -d '{"score":"17500", "score_date":"2019-01-01T03:02:00.776594Z", "player":"Gaston Hillar", "game":"Battlefield V"}' "localhost:8000/player-scores/"
    curl -iX POST -H "Content-Type: application/json" -d '{"score":"3225", "score_date":"2019-01-01T01:02:00.776594Z", "player":"Gaston Hillar", "game":"Mutant Football League: Dynasty Edition"}' "localhost:8000/player-scores/"
    curl -iX POST -H "Content-Type: application/json" -d '{"score":"43200", "score_date":"2019-01-01T03:02:00.776594Z", "player":"Enzo Scocco", "game":"Battlefield V"}' "localhost:8000/player-scores/"
    curl -iX POST -H "Content-Type: application/json" -d '{"score":"17420", "score_date":"2019-01-01T05:02:00.776594Z", "player":"Enzo Scocco", "game":"Mutant Football League: Dynasty Edition"}' "localhost: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": "Battlefield V",
        "id": 1,
        "player": "Gaston Hillar",
        "score": 17500,
        "score_date": "2019-01-01T03:02:00.776594Z",
        "url": "http://localhost:8000/player-scores/1/"
    }
    {
        "game": "Mutant Football League: Dynasty Edition",
        "id": 2,
        "player": "Gaston Hillar",
        "score": 3225,
        "score_date": "2019-01-01T01:02:00.776594Z",
        "url": "http://localhost:8000/player-scores/2/"
    }
    {
        "game": "Battlefield V",
        "id": 3,
        "player": "Enzo Scocco",
        "score": 43200,
        "score_date": "2019-01-01T03:02:00.776594Z",
        "url": "http://localhost:8000/player-scores/3/"
    }
    {
        "game": "Mutant Football League: Dynasty Edition",
        "id": 4,
        "player": "Enzo Scocco",
        "score": 17420,
        "score_date": "2019-01-01T05:02:00.776594Z",
        "url": "http://localhost:8000/player-scores/4/"
    }
  

We can run the previously explained commands to check the contents of the tables that Django created after executing the migrations process in the PostgreSQL database. We will notice that the game_id column for the games_playerscore table saves the value of the id 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 id of the related row in the games_player table. The following screenshot shows the contents for the games_esrb_rating, games_game, games_player, and games_playerscore tables in a PostgreSQL 10.5 database after running the HTTP requests:

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 is equal to 1. Don't forget to replace 1 with the id value of the player whose name is equal to 'Gaston Hillar' in your configuration. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd627.txt file:

    http ":8000/players/1/"
  

The following is the equivalent curl command. The code file for the sample is included in the restful_python_2_06_01 folder, in the Django01/cmd/cmd628.txt file:

    curl -iX GET "localhost:8000/players/1/"
  

The previous command will compose and send the following HTTP request: GET http://localhost:8000/players/1/. 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/1.1 200 OK
    Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
    Content-Length: 740
    Content-Type: application/json
    Date: Fri, 26 Oct 2018 03:13:15 GMT
    Server: WSGIServer/0.2 CPython/3.7.1
    Vary: Accept, Cookie
    X-Frame-Options: SAMEORIGIN
    
    {
        "gender": "M",
        "gender_description": "Male",
        "name": "Gaston Hillar",
        "scores": [
            {
                "game": {
                    "esrb_rating": "AO (Adults Only)",
                    "name": "Battlefield V",
                    "played_once": false,
                    "played_times": 0,
                    "release_date": "2017-05-01T01:02:00.776594Z",
                    "url": "http://localhost:8000/games/1/"
                },
                "id": 1,
                "score": 17500,
                "score_date": "2019-01-01T03:02:00.776594Z",
                "url": "http://localhost:8000/player-scores/1/"
            },
            {
                "game": {
                    "esrb_rating": "AO (Adults Only)",
                    "name": "Mutant Football League: Dynasty Edition",
                    "played_once": false,
                    "played_times": 0,
                    "release_date": "2018-10-20T03:02:00.776594Z",
                    "url": "http://localhost:8000/games/2/"
                },
                "id": 2,
                "score": 3225,
                "score_date": "2019-01-01T01:02:00.776594Z",
                "url": "http://localhost:8000/player-scores/2/"
            }
        ],
        "url": "http://localhost:8000/players/1/"
    }
  

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 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.119.133.228