/backgammon-back-end

DRF API for CI portfolio project 5

Primary LanguagePython

Tactical Rashers API

API welcome note

Live Site

Tactical Rashers API

Repository

backgammon-back-end


Table of Contents


Objective

This site is to represent capabilities with the Django Rest Framework. It should employ full Create, Read, Update, Delete (CRUD) functionality via DRF.

The assessment checklist is available to view in the docs/ directory of the project repository.

The needs within this project are not genuine and are made purely for the purpose of completing my Code Institute project.


Brief

Tactical Rashers API

Tactical Rashers : a backgammon players' site.

The site should allow users to play backgammon in a manner similar to "Chess by post". Users will be able to play private games, with dice rolls handled via the app, and comment with their intended moves. They should be able to update the main image of the game to the latest state of a board and should be able to declare a winner.

Full CRUD functionality should be available to allow users to interact appropriately with the various aspects of the finished application. This repo intends to provide a robust back-end API via the Django Rest Framework.


UX − User Experience Design

User Requirements

Some example user stories that will affect the design. Please consult the GitHub project board for a full list of user concerns written in the form of GitHub issues. Alternatively, a status graph can be viewed here.

Below is a non-exhaustive list of some of the user stories. Some of these are key user stories that must be achieved for an MVP to be considered complete:

First Time User

"As a potential player, I would like to be able to read the rules of the game so that I know how to play"

"As a potential user, I would like to be able to create a profile so that I am able to play"

Returning User

"As a returning user, I would like to quickly determine whether I am logged in so that I can log in / out as needed"

"As a returning user, I would like to log in to my account so that I can interact with the features of the site"

"As a returning user, I would like to view my currently active games so that I can track the progress of, and make new moves on, my games in play"

"As a returning user, I would like to play a game with another player so that I can enjoy the game of backgammon"

"As a returning user, I would like to comment on completed games so that I can interact with other users of the site"


Initial Concept

The back-end API should provide robust, well-handled database management for the front-end application. It should allow user authentication, game management, dice rolling and winner tracking. An optional consideration of "Follow gamer" - a feature that allows users to follow completed games of particular gamers - may be considered dependent on time constraints.


Features

Existing Features

  • Create account

    "As a potential user, I would like to be able to create a profile so that I am able to play"

    New users of the site can create a profile that enables the creation of, and participation in, games.

  • Log in

    "As a returning user, I would like to log in to my account so that I can interact with the features of the site"

    Existing users of the site can log in to their account.

  • Log out

    "As a signed in user, I would like to log out of my account so that I can protect my account on shared devices"

    Existing users of the site can log out of their accounts.

  • Create game

    "As a returning user, I would like to play a game with another player so that I can enjoy the game of backgammon"

    Existing users can create games with other players.

  • Find relevant games

    "As a returning user, I would like to play a game with another player so that I can enjoy the game of backgammon"

    "As a returning user, I would like to view my currently active games so that I can track the progress of, and make new moves on, my games in play"

    Games can be filtered and searched.

  • Roll dice

    "As a returning user, I would like to play a game with another player so that I can enjoy the game of backgammon"

    Dice rolls can be made in games.

  • Make a move

    "As a returning user, I would like to play a game with another player so that I can enjoy the game of backgammon"

    Moves can be noted in games.

  • Winner selection

    "As a returning user, I would like to play a game with another player so that I can enjoy the game of backgammon"

    Game winners can be specified.

  • Mark completed game

    "As a returning user, I would like to play a game with another player so that I can enjoy the game of backgammon"

    Games can be marked as active/complete.

  • Update game image

    "As a returning user, I would like to play a game with another player so that I can enjoy the game of backgammon"

    Game images can be updated by players.

  • Profile editing

    "As a potential user, I would like to be able to create a profile so that I am able to play"

    Users can update their profile with some information about themself and an avatar.

  • Display games records

    "As a returning user, I would like to view my currently active games so that I can track the progress of, and make new moves on, my games in play"

    Games can be filtered and searched and winners and move counts are tracked.


Future Features

  • Display game requests

    "As a returning user, I would like to play a game with another player so that I can enjoy the game of backgammon"

    Games can be initiated with any other player in the current iteration. It would be nice to implement a "request" feature that allows the requested player to accept/reject the invitation.

  • Comment on completed games

    "As a returning user, I would like to comment on completed games so that I can interact with other users of the site"

    This has not been worked on for this iteration. Adding this feature would encourage more social interaction with the site. A Comment model would be similar to the Move model and would only be available on games that are marked as complete (not active).

  • Mark game as public

    "As a returning user, I would like to play a game with another player so that I can enjoy the game of backgammon"

    "As a returning user, I would like to comment on completed games so that I can interact with other users of the site"

    This feature would allow all site users to view currently active games and, depending on the features permitted by the players, allow comments from non-players during the game. For this iteration, games will only be available to public and non-player users once they are marked as not active.


Features beyond the scope of the API

  • Rules

    "As a potential player, I would like to be able to read the rules of the game so that I know how to play"

    This will be handled by the front-end application.

  • Log in status

    "As a returning user, I would like to quickly determine whether I am logged in so that I can log in / out as needed"

    This will be handled by the front-end application.

Database Model

A PostgreSQL database has been used for storing the various data required for the API.

The database structure has been mapped out using an ERD diagram generated using the drawio extension in VSCode. Many of the entities will be linked back through the owner (Django auth's User model) which allows the database to have a straightforward structure. A few fields are missing from the ERD that record creation times and update times.

entity relationship diagram

Production Database

During development, the SQLite3 database provisioned by Django has been used. For the production build, an external PostgreSQL instance is necessary. Code Institute has provided a tool for their students that provides such a database. As the tool is only for students, and the steps are well defined within the application, the procedure to create this has not been detailed here. The URL provided via the tool meets the format required for the dj-database-url package: postgres://<username>:<password>@<host>/<database_name>

Many other PostgreSQL hosts will provide a URL in this format if required.

This URL is used in any non-development environment and is set as the DATABASE_URL environment variable.


Technologies Used

Python Packages

Some of the main packages used throughout the project:

Package Use
django web framework with effective PostgreSQL database handling methods
djangorestframework powerful and flexible toolkit for building Web APIs
djangorestframework-simplejwt JSON Web Token authentication plugin
django-filter allow QuerySet filtering from URL parameters
cloudinary easy uploading of media files to Cloudinary
load-dotenv reads key-value pairs from a .env file
gunicon Python WSGI HTTP Server for UNIX
psycopg2 PostgreSQL database adapter for Python

For a full list of installed Python packages, see requirements.txt

Most packages have relevant documentation hosted on the Python package index site.

Other Tech

A screenshot tool built into Windows. It allows quick, partial screenshots to be taken that can be saved as image files.

A free, streamlined code editor. The extensions available have allowed me to customize my workspace and become more efficient.

VSCode Extensions

Links to the VSCode marketplace for each extension used throughout this project:

Testing

Manual Testing

Manual testing was performed during the development cycle. As the database is fairly straightforward, there were very few bugs identified during the process. Testing consisted of logically creating, reading, updating and deleting records where necessary.

  • Multiple users were created to allow testing of various relationships between the models.
  • Games can be created by the logged-in user with another user successfully.
  • Games cannot be created by a logged-in user with themself.
  • Games cannot be created by a logged-in user between two other users.
  • Moves were only available to relevant players and at relevant times.
  • Winners could only be selected by anticipated users.
  • Dice rolls could not be manually determined.
  • Profile access is limited to the appropriate level of CRUD depending on user login status.
  • Users can log in and out.

Automated Testing

The nature of the project allowed for fairly robust automated testing. Several tests were written utilizing the APITestCase class available through rest_framework.test. I was not aware of how straightforward the test-writing procedure would be for the application and would consider a TDD approach for future development. There were a few items that needed editing that were identified during the writing of tests. Those items have been updated.

Tests were written in a logical order to allow the flow of the site to be incorporated during the process. This allowed functions to be used to create users and games, reducing the need to duplicate code. However, many lines of code are similar in the tests and this is done with intention. The tests are clear, thorough, and easily maintained separately from each other.

Please consult the test.py files for the test code, and consult the manage.py test output file for all tests run. As shown within that file, 83 tests have been run on the database covering a wide range of functionality and defensive programming. The test time is fairly long due to the DiceRolls test that ensures dice rolls are random. I could not think of a more efficient (or certain) way of testing this feature, so 25 dice rolls are generated and compared for uniqueness and their correct parameters.

PEP8 Testing

The Python files have all been checked using flake8. As shown, the command flake8 . --exclude .venv/,__pycache__/,**/migrations/** was used to run a check on the entire project directory, excluding the directories passed in as arguments. No other errors or warnings are reported.
flake8 results

Doc strings and comments are included where I feel the logic or code needs explaining beyond its implicit readability, with closing brackets clearly showing where arguments etc. are finished. The only exceptions to this are the migration files that were generated by Django.

HTML, CSS and JavaScript

No HTML, CSS or JavaScript validation has been carried out on the API front end as this will not be utilized in the final project and is not my own code.

Bugs

Current

At the time of deployment, no current bugs have been found. Some features are yet to be implemented, but all functionality is working as intended for this iteration.


Resolved

  1. Winner relationships were incorrect

a game needed a winner

Commit - a925c74

During manual testing and the improvement of back-end defensive programming, it became evident that the Winner model was incorrectly configured. This was resolved by implementing a ForeignKeyField with unique=True. This generates a warning that a OneToOneField is more appropriate, but that would not allow for a Game with no Winner without allowing it the other way as well (Winner without a Game).
The warning (fields.W342) has been silenced in the settings.py file [421eb47].


Commit - c64e2aa

During the creation of automated tests, it was identified that players could potentially create games that did not include themselves as a participant. Although this is not a breaking issue, and would likely require some front-end code manipulation when submitting a request, it was simple enough to resolve with the addition of a custom perform_create method. The discovery of this bug led to another few custom methods being written to prevent erroneous instances from being created. The image below shows a Move being added to a game in which the author was not a participant.

an erroneous game instance


Agile

A GitHub project was created for the site's development. The project is shared between the back-end API and the front-end React application. Labels have been used to help organize the tasks involved and can be filtered as needed. There are multiple views already available on the Project.

An Agile approach has been used to ensure an MVP has been created in time for release (project submission). Issues have sprint points assigned for their effort to complete and have been assigned to Milestones to reflect a sprint process. Sprints were started with a total story point availability of 20 and reviewed at the end of the sprint. The sprint point availability for my efforts was adjusted to allow a maximum of 25 within a sprint as the initial value was not reflective of my ability.

Separate views have been created for each sprint to allow a clear visual of the progress being made. Separate views for docs and user stories also exist for an overview.

Development

The site was developed using git, GitHub and VSCode. The repository is available for cloning or forking but no additional contributions will be accepted at this time.

To clone the repo please see the steps below.

  • Sign in to GitHub.

GitHub dashboard

GitHub dashboard

  • Proceed to your chosen method of cloning a repo and provide the copied URL when needed.

I have a number of extensions installed to aid my development in VSCode. The steps below work for me, but alternative methods are available. Please consult the relevant docs for various approaches.

  • Open a bash terminal within VSCode and navigate to a parent directory for your repository.

bash terminal

  • Enter git clone https://github.com/DaveyJH/backgammon-back-end.git (the URL copied from GitHub). This will clone the repository into a new directory called backgammon-back-end.

clone command

  • Enter the command cd backgammon-back-end && code . -r to open the repository in the current VSCode window.

open in VSCode command

  • Create and activate a virtual environment within the directory. I use venv for this via python -m venv .venv && . .venv/scripts/activate.

venv creation and activation

  • Install the requirements for the repository using pip install -r requirements.txt.

requirements installation

  • Ensure you have created the necessary env variables in a .env file.

env file example

Development .env

As mentioned above in the Python packages section, I utilized a .env file for my environment variables. If you intend to run this application from a clone of the repository, you will need your own file with the following key-value pairs:

key value
SECRET_KEY a secret key - this can be generated using python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())' within your terminal
HOST the IP address or host name where the server will be run
CLOUDINARY_URL a Cloudinary account API Environment variable, available from a Cloudinary account dashboard
DEVELOPMENT optional configures the authentication method of the django rest framework API and connects the django project to an db.sqlite3 instance for use in a development environment
DEV optional configures the response format of the django rest framework API to allow a front-end interactive representation
CLIENT_ORIGIN_DEV optional allows cross-site http requests from an alternate URL to the server

Additional key-value pairs are required for a deployed application. Please see the section below for more detail

Deployment

The API is deployed on Heroku; the steps below detail the process to achieve this.

  1. Run pip freeze > requirements.txt to ensure all Python packages are available for the production build.
  2. Ensure you have a Procfile with the following content:
     release: python manage.py makemigrations && python manage.py migrate
     web: gunicorn backgammon_drf.wsgi
    
  3. Navigate to your Heroku dashboard
  4. Click "New" and select "Create new app".
    New button on Heroku
  5. Input a meaningful name for your app and choose the region best suited to your location.
    Create new app
  6. Select "Settings" from the tabs.
    Settings tab
  7. Click "Reveal Config Vars".
    Config vars button
  8. Input the required key-value pairs from the .env file. Ensure DEBUG and DEVELOPMENT are not included. Config vars Keys to include:
    • SECRET_KEY (generate a new key for production)
    • CLOUDINARY_URL
    • HOST (for this value, right-click "Open app" and copy the link address, deleting "https://")
    • DATABASE_URL (see Production Database section)
    • CLIENT_ORIGIN (production - this will be the URL of your front-end app)
    • CLIENT_ORIGIN_DEV (development - this will be the URL of your front-end development server)
  9. Select "Deploy" from the tabs.
    Settings tab
  10. Select "GitHub - Connect to GitHub" from deployment methods.
    Select GitHub
  11. Click "Connect to GitHub" in the created section.
    Connect to GitHub
  12. Search for the GitHub repository by name.
    Heroku repo search
  13. Click to connect to the relevant repo.
    Heroku connect to repo option
  14. Either click Enable Automatic Deploys for automatic deploys, or Deploy Branch to deploy manually. Manually deployed branches will need re-deploying each time the repo is updated.
    Heroku deploy branch
  15. Click View to view the deployed site.
    Heroku view

The live site can also be accessed from your repo in GitHub from the Deployments section of the repo.

  • Click the link to view the deployment history. GitHub Deployments
  • Click the provided URL. GitHub view deployment

Credits

Media

Acknowledgments

Thanks to @CluelessBiker, my mentor for the project, as she helped me focus on the MVP and gave great support regarding the project planning process.

As always, the wonderful staff at Code Institute for introducing me to this framework and providing me with the foundations to start developing this API.


Personal Development

I am pleased with how quickly this project has gone together. I would enjoy working with the framework again and would approach things with a TDD mindset!