The structure of the projects follows for most parts the following guidelines https://github.com/HackSoftware/Django-Styleguide. Shortly, every app has a selector
file where the reading operations business logic lives and a service
file for the writing operations.
Rest Framework serializers are used only to serialize object and to check validity for input data. Validation in general is inside the models clean
method and on models constraints
.
Authentication is handled by djangorestframework-simplejwt
library and filtering is handled by django-filter
library.
-
common/models:BaseModel
Abstract model to handle common columns
-
user/models:UserCustom
Simply inherits from Django default
AbstractUser
model.
-
movie/models:Movie
Has a title and a genre. It has a many-to-many relationship with
User
by theUserWatchedMovie
through table, a many-to-many relationship withPlatform
, a many-to-many relationship withUser
by theUserRecommendMovie
through table. -
movie/models:Platform
A movie can belongs to different platform and viceversa
-
recommendation/models:UserRecommendMovie
Bridge table for many-to-many relation
Movie-UserCustom
, it has aunique_toghether
constraint so that one user can recommend only a movie. It halso has avote
anddescription
attribute related to the recommendation.
-
user/views:UserRegistrationView
/user/register
Creates a new user
body
{ "username": "user1", "email": "user1@mmail.com", "password": "Passw0rd!" }
example
curl -X POST 'http://127.0.0.1:7777/user/register' \ --header 'Content-Type: application/json' \ --data '{ "username": "user1", "email": "user1@mmail.com", "password": "Passw0rd!" }'
/user/login
body
{ "username": "user1", "email": "user1@mmail.com", "password": "Passw0rd!" }
example
curl -X POST 'http://127.0.0.1:7777/user/login' \ --header 'Content-Type: application/json' \ --data '{ "username": "user1", "password": "Passw0rd!" }'
/user/login/refresh
to refresh JWT token
-
movie/views:MovieListCreateView
Authentication is required only for writing operation.
For reading operation it can leads to different result, for instance the possibility to filter by watched/unwatched movies
/movie/
GET
Returns the list of movies with recommendation and platform references.
-
Available filters:
platform: str
has_watched: bool
recommend_by: str
recommend_by_others: bool
-
Available ordering options:
order_by_title: str
example no auth
curl -X GET "http://127.0.0.1:7777/movie/" \ --header "Content-Type: application/json"
example auth
BEARER_TOKEN="" curl -X GET "http://127.0.0.1:7777/movie/" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $BEARER_TOKEN"
POST
Creates a new movie
body
{ "title": "IT", "genre": "HORROR", "platforms": [ { "name": "NETFLIX" } ] }
example
BEARER_TOKEN="" curl -X POST "http://127.0.0.1:7777/movie/" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $BEARER_TOKEN" \ --data '{ "title": "IT", "genre": "HORROR", "platforms": [ { "name": "NETFLIX" } ] }'
-
-
movie/views:MovieRetrieveView
/movie/{slug-title}
GET
Returns the detail of a single movie
example no auth
curl -X GET "http://127.0.0.1:7777/movie/{movie-slug-title}" \ --header "Content-Type: application/json"
example auth
BEARER_TOKEN="" curl -X GET "http://127.0.0.1:7777/movie/{movie-slug-title}" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $BEARER_TOKEN"
-
movie/views:MovieSwitchWatched
/movie/{slug-title}
POST
Set and unset the association between a user that watched a movie
example
BEARER_TOKEN="" curl -X POST "http://127.0.0.1:7777/movie/switch_watched/{movie-slug-title}" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $BEARER_TOKEN"
-
recommendation/views:RecommendationMovieListCreateView
Authentication is required only for writing operation.
/recommendation/movie/{slug-title}
GET
Returns the list of all recommendation for a given movie.
-
Available filters:
platform: str
user: str
-
Available ordering options:
order_by: Literal['vote', 'platform']
example
curl -X GET "http://127.0.0.1:7777/recommendation/movie/{slug-title}" \ --header "Content-Type: application/json"
POST
Creates a new recommendation. If the specified platform was not yet associated to the movie, will be added to the available platforms of the movie
body
{ "vote": 7, "comment": "nice", "platform": { "name": "DISNEY_PLUS" } }
example
BEARER_TOKEN="" curl -X POST "http://127.0.0.1:7777/recommendation/movie/{slug-title}" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $BEARER_TOKEN" \ --data '{ "vote": 7, "comment": "nice", "platform": { "name": "DISNEY_PLUS" } }'
-
-
recommendation/views:RecommendationUserListView
/recommendation/user/{username}
GET
Returns the list of all recommendation for a given user.
-
Available filters:
platform: str
user: str
-
Available ordering options:
order_by: Literal['vote', 'platform']
example
curl -X GET "http://127.0.0.1:7777/recommendation/user/{username}" \ --header "Content-Type: application/json"
-
The Django server is exposed on port 7777
docker compose -f django_movie_recommendation/docker/docker-compose.yaml up --build
To run tests, from a different terminal run
docker exec movie_recomm python django_movie_recommendation/manage.py test tests
- pagination
- complete tests
- caching