Implement voting REST API for choosing where to go to lunch.
Basic business rules/requirements
-
Everyone can add/remove/update restaurants
-
Every user gets X (hardcoded, but "configurable") votes per day.
1st user vote on the same restaurant counts as 1 2nd = 0.5 3rd and all subsequent votes, as 0.25.
2.1. If a voting result is the same in a couple of restaurants, the winner is the one who got more distinct users to vote on it.
-
Every day vote amounts are reset. Not used previous day votes are lost.
-
Show the history of selected restaurants per time period
-
Do not forget, that frontend dev will need a way to show on what restaurants users can vote and what restaurant is a winner.
-
Readme on how to use API, launch project etc
If the app would be wrapped in docker, it would be great, but not mandatory. Bonus points, API is deployed somewhere (For example, Heroku)`
- django project
- django app for API
- documentations
- django app routes
- requirements
- Everyone can add/remove/up...
- Every user gets X (hardcod...
- Every day vote amounts ar...
- Show the history of selec...
- Do not forget, that front...
- API routes dump in docs [WIP]
- docker container + docker compose
- production on Heroku or better
First we start by cloning the project's repo
git clone https://github.com/gnud/restaurant_rater.git
now, cd into our project
virtualenv -p python3 venv
source venv/bin/activate
Note: we can replace venv with ~/.venvs/restaurant_rater_venv or any full path to some venvs directory
pip install -r requirements.txt
Note: make sure virtualenv is loaded.
Do initial migration first
./manage.py migrate
Now setup a cache table for the cache database backend
./manage.py createcachetable
A guest user can browse API docs via the Insomnia viewer web interface, provided via http://127.0.0.1:8000/docs/index.html
A docker based server can be visited by http://localhost:8000/docs/index.html A production server can be visited by http://localhost:8000/docs/index.html
./manage.py runserver
Note: Working directory must be the project's root
gunicorn -c restaurant_rater/gunicorn.conf.py restaurant_rater.wsgi:application --preload
Create a new Python Run configuration, named Gunicorn or whatever.
Find path:
- Find the full gunicorn path, use
which gunicorn
in your projects path when virtualenv is loaded to find the full path. - Or find it by hand in myvenv/bin/gunicorn.
Note: if gunicorn is not found, make sure you install all packages from requirements.txt.
Apply full path in Script path.
In Parameters paste this '-c gunicorn.conf.py wsgi:application --preload'
- wsgi:application - means wsgi.py which is located in restaurant_rater/wsgi.py as python module and application is variable an instance of WSGIHandler.
Working directory should be set as "restaurant_rater/restaurant_rater" using it's full path, not relative - where restaurant_rater is the root project path, and restaurant_rater is the Django project's python package.
After saving the Run configuration try running it with run/debug
Expected to see:
... Random config verbose garbage
[2020-11-01 16:01:01 +0000] [29684] [INFO] Starting gunicorn 20.0.4
[2020-11-01 16:01:01 +0000] [29684] [DEBUG] Arbiter booted
[2020-11-01 16:01:01 +0000] [29684] [INFO] Listening at: http://0.0.0.0:8000 (29684)
[2020-11-01 16:01:01 +0000] [29684] [INFO] Using worker: sync
[2020-11-01 16:01:01 +0000] [29684] [DEBUG] 1 workers
[2020-11-01 16:01:01 +0000] [29694] [INFO] Booting worker with pid: 29694
An admin user can login via the admin web interface, provided via http://127.0.0.1/admin/
./manage.py createsuperuser --username='petko' --email='petko@example.com'
# <type a password>
Login with sample user and the owner can see Menus admin page.
The browsable API located at http://127.0.0.1:8000/api/v1/restaurant/
To run RestaurantTests
./manage.py test api.tests.RestaurantTests
To run VotingTests
./manage.py test api.tests.VotingTests
To run HistoryTests
./manage.py test api.tests.HistoryTests
This Dockerfile is based on the official Python image and it's full version including and OS, vim and less.
Docker-compose is being added to manage the services.
Note: for less complexity no database server was chosen, there for we have mounted the "docker/data/db.sqlite3" for the database to the root path of the django project
Building
docker-compose build
docker-compose up -d
Logs
docker-compose logs -f
NOTE: Control the log level via the env var APP_GUNICORN_LOGLEVEL: info, debug see gunicorn docs for more.
docker-compose up -d
docker-compose stop dj-api
docker-compose exec dj-api python manage.py
Now we can use:
- manage.py migrate
- manage.py collectstatic
- manage.py createsuperuser when needed.
To access the shell in the container:
docker-compose exec dj-api bash
- Migrate database
docker-compose exec dj-api python manage.py createcachetable
- collectstatic
docker-compose exec dj-api python manage.py collectstatic
- Cache table for the cache database backend
docker-compose exec dj-api python manage.py createcachetable
Our Django project root is located in /app/ Contains only the minimum required files to run Django, controlled via .dockerignore.
URLS: