Skip to content

hack4impact-uiuc/backend-exercise

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Flask Exercise

Note: this repo is intended for Hack4Impact UIUC members. If you are interested in learning from this exercise, please use this repo instead!

This exercise is intended for you to get familiar with fundamental backend/server side programming in an interactive way, as well as for you to get comfortable developing in a modern Python/Flask environment.

Reading the following will help you get a sense of the big picture when it comes to developing APIs/writing server side code, and how it fits in the context of a larger web application:

This project will be broken down into multiple parts. After you finish this project, submit a pull request and assign your tech lead to review it!

This exercise is due before the next all hands meeting (Sunday Feb 18th). However, the sooner you put up your PR, the sooner you will get a review, and the faster you will get feedback and learn!

Note that the initial Circle CI builds will fail because the tests encompass functionality that you will implement!

Guidance

We understand that a lot of you are new to Flask and backend development in general. We think going through this exercise will really help you get up to speed in order to start being productive contributing to your nonprofit project.

A lot of what makes a good software developer is being resourceful and knowing where/how to find information you need. At the same time, the entire Hack4Impact community is available if you get stuck, have unanswered questions, or want to discuss anything!

Ask questions and discuss about python as a language and its features or syntax in the #python Slack channel.

Ask questions and discuss about Flask, creating endpoints, or any other backend related topics in the #backend Slack channel.

And of course, if you are already familiar with this or have figured it out, please hop in these channels and help those who need it! :)

Requirements

  • python version 3.x
  • pip
  • pipenv
  • Postman

Installation instructions for Mac and Windows

Check if you have the correct versions by running the following commands in your terminal:

python3 -V
pip3 -V
pipenv --version

Setup

First, clone this repository and go into it:

$ git clone https://github.com/hack4impact-uiuc/backend-exercise.git
$ cd backend-exercise

Then, setup your virtual environment and install the python dependencies required to run this app. We use pipenv, which automatically sets everything up, given a Pipfile and Pipfile.lock. Pipfile uses virtualenv, which is a virtual Python environment isolated from other Python projects, incapable of interfering with or being affected by other Python programs on the same machine. You are thus capable of running different versions of the same package or even different python versions.

pipenv install

You must be in this virtual environment to start this server. To do that:

pipenv shell

Then, to start the server run:

(backend-exercise-o4dc6oDL)$ python app.py

Note: This will remain a running process in your terminal, so you will need to open a new tab or window to execute other commands.

To stop the server, press Control-C.

To exit your virtual environment, which is named backend-exercise-[something here], run:

(backend-exercise-o4dc6oDL)$ deactivate

You can also add pipenv run before any command instead of having to run pipenv shell. eg pipenv run python app.py

Before you make any changes to the code, make sure to create a new branch. Typically branches are named based on the feature or bugfix being addressed, but for this project, name your branch with your own name so your reviewer can easily follow:

git checkout -b <YOUR_NAME>

Branch names should be all lowercase and can't contain spaces. Instead of spaces, use hyphens. For example:

git checkout -b varun-munjeti

Running The Server And Calling Endpoints

Starting the server will make it a continuously running process on localhost:5000. In order to make requests to your server, use Postman.

First, make a GET request to the / endpoint. Since the server is running on localhost:5000, the full endpoint url is localhost:5000/.

Postman GET

Try calling the /mirror endpoint. First, look at the code for the endpoint to see how you can specify url parameters. Then make a request on Postman to localhost:5000/mirror/<name>:

Postman GET mirror

Exercises

These exercises will walk you through creating a RESTful API using Flask! We don't want you to go through all the hassle of setting up a database instance, so we have created dummy data and a mock database interface to interact with it. For the sake of ease, the entire app logic minus the mockdb logic will by implemented in app.py. For larger projects, the API endpoints will usually be separated out into different files called views.

Before you start, take a good look at the create_response function and how it works. Make sure you follow the guidelines for how to use this function, otherwise your API will not follow the proper conventions!

Also take a look into the mock database. The initial dummy data is defined in mockdb/dummy_data.py. This is what will "exist" in the "database" when you start the server.

The functions defined in mockdb/mockdb_interface.py are how you can query the mockdb. In app.py, where you will be writing your API, this has been imported with the name db. Therefore when you write the code for your endpoints, you can call the db interface functions like db.get('users').

When you modify your code, the server will automatically update, unless your code doesn't compile, in which case the server will stop running and you have to manually restart it after fixing your code.

Part 1

Define the endpoint:

GET /users

This should return a properly formatted JSON response that contains a list of all the users in the mockdb. If you call this endpoint immediately after starting the server, you should get this response in Postman:

{
  "code": 200,
  "message": "",
  "result": {
    "users": [
      {
        "age": 19,
        "id": 1,
        "name": "Aria",
        "team": "LWB"
      },
      {
        "age": 20,
        "id": 2,
        "name": "Tim",
        "team": "LWB"
      },
      {
        "age": 23,
        "id": 3,
        "name": "Varun",
        "team": "NNB"
      },
      {
        "age": 24,
        "id": 4,
        "name": "Alex",
        "team": "C2TC"
      }
    ]
  },
  "success": true
}

Part 2

Define the endpoint:

GET /users/<id>

This should retrieve a single user that has the id provided from the request.

If there doesn't exist a user with the provided id, return a 404 with a descriptive message.

Part 3

Extend the first /users enpoint by adding the ability to query the users based on the team they are on. You should not use a url parameter like you did in Part 2. Instead, use a query string.

If team is provided as a query string parameter, only return the users that are in that team. If there are no users on the provided team, return an empty list.

For this exercise, you can ignore any query string parameters other than team.

In Postman, you can supply query string parameters writing the query string into your request url or by hitting the Params button next to Send. Doing so will automatically fill in the request url.

The following should happen

GET /users?team=LWB

{
  "code": 200,
  "message": "",
  "result": {
    "users": [{
      "age": 19,
      "id": 1,
      "name": "Aria",
      "team": "LWB"
    }, {
      "age": 20,
      "id": 2,
      "name": "Tim",
      "team": "LWB"
    }]
  },
  "success": true
}

Postman Query String Request

Part 4

Define the endpoint:

POST /users

This endpoint should create a new user. Each request should also send a name, age, and team parameter in the request's body. The id property will be created automatically in the mockdb.

A successful request should return a status code of 201 and return the newly created user.

If any of the three required parameters aren't provided, DO NOT create a new user in the db and return a 422 with a useful message. In general, your messages should provide the user/developer useful feedback on what they did wrong and how they can fix it.

This is how you can send body parameters from Postman. Make sure you don't mistake this for query parameters! Postman POST

Part 5

Define the endpoint:

PUT /users/<id>

Here we need to provide a user's id since we need to specify which user to update. The body for this request should contain the same attributes as the POST request from Part 4.

However, the difference with this PUT request is that only values with the provided keys (name, age, team) will be updated, and any parameters not provided will not change the corresponding attribute in the user being updated.

You do not need to account for body parameters provided that aren't name, age, or team.

If the user with the provided id cannot be found, return a 404 and a useful message.

Part 6

Define the endpoint:

DELETE /users/<id>

This will delete the user with the associated id. Return a useful message, although nothing needs to be specified in the response's result.

If the user with the provided id cannot be found, return a 404 and a useful message.

Part 7 - Tests

Let's write unit tests! Unit tests are very important to software development. It enables to automatically check whether our functionality works or not since manually testing everything is very slow and error prone. Test Driven Development is a software development process in which we define a specification, write tests to that spec, then implement the functionality, and use the tests to validate whether it works. We've done a bit of that for you as the tests for Part 1-3 are written. To test them:

pipenv install --dev
pipenv run pytest

If your changes worked, you should see a green line saying 5 passed. If they don't, follow the stack traces and fix your implementation. Once they work, let's write tests for the Parts 3-6.

We use pytest, a useful python test framework that automatically finds and runs python methods that start with test, such as test_get_index. In our case, we have a test file named test_app.py, which holds all the tests for Parts 1-3.

Each method also accepts a client object, which is automatically injected by pytest. client is a test fixture, which is something that you may use in multiple tests, giving you a fixed baseline for your tests. When initializing, pytest looks into conftest.py and collects all fixtures. In our case, we have a client fixture, which gives a flask test client, which we can use to easily test our API. Look into how you can use the Flask test client to make other types of requests and how you can use the request payload.

Submitting

When you're done with all the steps, open a pull request (PR) and assign your tech lead to review it!

Let's run black, a python formatter, before you submit. This removes all arguments on how we want to style your python code and gives reviewers a standardized style to review from. You must have it installed with pipenv install --dev

pipenv run black .

Before you can submit a PR, you'll have to push your branch to a remote branch (the one that's on GitHub, not local).

Check to see that you're on your branch:

git branch

If you want to make sure all of your commits are in:

git log

Press Q to quit the git log screen.

Push your commits to your remote branch:

git push

The first time you do this, you might get an error since your remote branch doesn't exist yet. Usually it will tell you the correct command to use:

git push --set-upstream origin <YOUR_BRANCH_NAME>

Note: this only needs to be done the first time you push a new branch. You can use just git push afterwards.

If you go to your branch on github, you may see a green checkmark next to a commit. We a Circle CI continuous integration set up that automatically runs your tests. If they pass, you will have a green check mark.

Follow the instructions on the wiki to open the PR.

For this specific PR, since this repo is forked, there are a couple extra steps you need to do for your PR.

When you create your PR on github, by default it'll want to make a PR for Aria's repo.

First, we need to choose H4I's repo as the base: PR Base

Then, choose your branch (using Dean's as an example): PR Branch

Note: make sure that you don't actually merge your PR in! We are only using it as a mechanism for providing code reviews.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%