Making with Code

Riddle Server #

In this lab we are going to learn how the riddle server is made using Banjo.

πŸ“– Open the Banjo documentation: the-isf-academy.github.io/banjo_docs/


[0] Set Up #

πŸ’» Download Mac app of HTTPIE: httpie.io/download. We need to download the app to make local HTTP requests for testing purposes. In this lab, you will run a locally hosted riddle server on your laptop using Banjo.

πŸ’» Start by going into the unit folder and the lab. Remember to replace yourgithubusername with your actual GitHub username.

cd ~/desktop/making_with_code/unit03_networking/
cd lab_banjo_yourgithubusername
πŸ’» Upgrade versions
poetry update
πŸ’» Enter the Poetry shell
poetry shell

[1] Local Riddle Server #

You are each able to run a locally hosted riddle server on your laptop using Banjo.

Starting the Server #

πŸ’» Now, let's start your local server. We use --debug to provide more information when in the development stage.

banjo --debug
No changes detected in apps 'app', 'banjo'
Operations to perform:
  Apply all migrations: admin, app, auth, contenttypes, sessions
Running migrations:
  No migrations to apply.
No changes detected in apps 'banjo', 'app'
Operations to perform:
  Apply all migrations: admin, app, auth, contenttypes, sessions
Running migrations:
  No migrations to apply.
Performing system checks...

System check identified no issues (0 silenced).
September 16, 2022 - 02:40:21
Django version 4.1.1, using settings 'banjo.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Accessing the Server #

πŸ’» You can now visit this server in your web browser, just as you did with the riddler server hosted on the internet: 127.0.0.1:8000/riddle/all

πŸ’» Open the HTTPie desktop app to send the same GET request to /all.

Look at the Terminal window running the server. Notice how it recorded your request.
[16/Sep/2024 02:44:20] "GET /riddle/all HTTP/1.1" 200 1069

πŸ’» Send a POST request to the /new endpoint.

Payload:

  • question (str)
  • answer (str)
Look at the Terminal window running the server. Notice how it recorded your request.
[01/Sep/2024 20:56:22] "POST /riddle/new?id=1 HTTP/1.1" 200 127

Your version of the riddle server only has the 2 endpoints:

  • /riddle/all
  • /riddle/new
βœ… CHECKPOINT:

πŸ’» Explore both endpoints via the HTTPie desktop app and be sure to successfully:

  • view all riddles without the answers
  • create a new riddle


[2] What is Banjo? #

This server is written using Banjo, a wrapper for Django. It allows users to quickly create models with a persistant database and API.

πŸ“ Banjo apps must have an app folder. Within the app folder must be two files: models.py, views.py. The database.sqlite file is created when the server is first started. It is stored at the same level as app. Here is an example file structure:

lab_banjo
|
└──app
|   β”œβ”€β”€models.py
|   └──views.py
└──database.sqlite
  • models.py - This defines what the database will look like. Models are a lot like classes. Just as a class has properties, a model has fields. When defining a model’s fields, you must specify the data type.
  • views.py - The views are where you define the API functionality. Here is where you decide what the endpoints are and the type of HTTP request it will require.

πŸ“„ In this lab, we are going to be primarily focused on the views.py file.


[3] Writing Routes #

In this lab, you will build out the functionality of the Riddle server. Currently, your file only has riddle/all and riddle/new.

It is up to you to add the following endpoints:

  • riddle/one
  • riddle/guess
  • riddle/difficulty
  • riddle/random

πŸ’» Start by opening up the primary folder: /app

code app

πŸ‘Ύ πŸ’¬

Open a new terminal tab using ⌘ + T.
You can have your server running in one tab, and use the other tab to access your filesystem.


πŸ’» Open the views.py file. Here is where you will write the additional endpoints.

πŸ“– Open the Banjo Views Documentation: the-isf-academy.github.io/banjo_docs/ You will need to reference this and the exisiting routes in views.py.


riddle/one #

πŸ’» Write the riddle/one endpoint.

  • HTTP method: get
  • Payload/args: id
  • Return: a single Riddle with the question, guesses, and correct properties

πŸ€” Which method in the Riddle model could be useful?

βœ… CHECKPOINT:

πŸ’» Test the riddle/one endpoint in the HTTPie desktop app

http://127.0.0.1:8000/riddle/one

βœ”οΈ It should return json like:

{
  "riddle": {
    "id": 1,
    "question": "I’m light as a feather, yet the strongest person can’t hold me for five minutes. What am I?",
    "guesses": 43,
  "correct": 1
  } 
}


riddle/guess #

πŸ’» Write the riddle/guess endpoint.

  • HTTP method: post
  • Payload/args: id and guess
  • Return:
    • if the guess was correct
      • message telling the user they were correct
      • a single Riddle with the id, question, guesses, correct, and answer properties
    • if the guess was incorrect
      • message telling the user they were incorrect
      • a single Riddle with the id, question, guesses, and correct, properties

πŸ€” Which method in the Riddle model could be useful?

βœ… CHECKPOINT:

πŸ’» Test the riddle/guess endpoint in the HTTPie desktop app

http://127.0.0.1:8000/riddle/guess

βœ”οΈ It should return json like:

{
  "riddle": {
    "id": 1,
    "question": "I’m light as a feather, yet the strongest person can’t hold me for five minutes. What am I?",
    "guesses": 44,
    "correct": false
  }
}


riddle/difficulty #

πŸ’» Write the riddle/difficulty endpoint.

  • HTTP method: get
  • Payload/args: id
  • Return:
    • a single Riddle with the id, question, and difficulty properties

πŸ€” Which method in the Riddle model could be useful?

βœ… CHECKPOINT:

πŸ’» Test the riddle/difficulty endpoint in the HTTPie desktop app

http://127.0.0.1:8000/riddle/difficulty

βœ”οΈ It should return json like:

{
  "riddle": {
    "id": 1,
    "question": "I’m light as a feather, yet the strongest person can’t hold me for five minutes. What am I?",
    "difficulty": 0.9555555555555556
  }
}


riddle/random #

πŸ’» Write the riddle/random endpoint.

  • HTTP method:get
  • Payload/args: none
  • Return: a single Riddle with the id, question, correct, and guess properties

πŸ€” Which query method may be useful? Be sure to reference the Banjo documentation.

βœ… CHECKPOINT:

πŸ’» Test the riddle/random endpoint in the HTTPie desktop app

http://127.0.0.1:8000/riddle/random 

βœ”οΈ It should return json like:

{
  "riddle": {
    "id": 6,
    "question": "The more you take, the more you leave behind. What am I?",
    "guesses": 4,
    "correct": 0
  }
}


[4] Deliverables #

⚑✨

Once you’ve successfully completed the worksheet be sure to fill out this Google form.

πŸ’» Push your work to Github:

  • git status
  • git add -A
  • git status
  • git commit -m “describe your code and your process here”

    be sure to customize this message, do not copy and paste this line

  • git push


[5] Extensions #

View Solution #

Currently, there’s no way to see the answer unless you correctly guess the riddle.

πŸ’» Write an endpoint that has the ability to view the solution of a given Riddle.

  • an existing Riddle class may be useful

It should return JSON that looks something like:

{
    "riddle": [
        {
            "correct": 0,
            "guesses": 3,
            "id": 1,
            "question": "It goes up and down the stairs without moving.",
            "answer": "A carpet"
        }
    ]
}

Change Question and Answer #

πŸ’» Write an endpoint that has the ability to change the question a riddle.

  • *It may be helpful to write a new method change_question()
MethodURLRequired PayloadAction
POST/change/questionnew_questionReturns thee riddle with the new answer

πŸ’» Write an endpoint that has the ability to change the answer a riddle.

  • *It may be helpful to write a new method change_answer()
MethodURLRequired PayloadAction
POST/change/answernew_answerReturns the riddle with the new answer

Difficulty Level Endpoint #

Because we track difficulty, it would be nice if we could GET a list of riddles of easy, medium, or hard difficulty.

πŸ’» Write an endpoint returns riddles within a difficulty category

  • a Riddle with a difficulty of 1 is impossibly hard, while a Riddle with a difficulty of 0 is easy–everyone gets it right!
MethodURLRequired PayloadAction
GET/all/difficultylevel (easy, medium, or hard)Returns a list of riddles of the appropriate difficulty level

βœ”οΈ It should return json like:

{
  "difficulty_level": "hard",
 "riddles": [
    {
      "correct": 1,
      "guesses": 44,
      "id": 1,
      "question": "I’m light as a feather, yet the strongest person can’t hold me for five minutes. What am I?",
      "difficulty": 0.9555555555555556
    },
    {
      "correct": 4,
      "guesses": 9,
      "id": 2,
      "question": "What comes down but never goes up?",
      "difficulty": 0.875
    }
 ]
}

Like field #

What if we want to know which riddles people like? For this, we will have to add allow users to like a riddle.

Let’s make the Riddle keep track of likes. You will need to edit models.py

πŸ’» Let’s make the Riddle keep track of likes. You will need to edit models.py You will need add a new field and write a new method.

πŸ’» Add a new endpoint for you to get all Riddle objects of a category

MethodURLRequired PayloadAction
POST/one/likeidReturns a single riddle with the likes
{
  "riddle": {
    "id": 1,
    "question": "I’m light as a feather, yet the strongest person can’t hold me for five minutes. What am I?",
    "guesses": 43,
    "correct": 1,
    "likes": 10
  } 
}