This is a Django REST based media manager designed with an adaptive & hierarchical file structure. Popflix would function as an ideal API back-end for any media manager project whether the key file type was audio, video, text etc, etc. There is a full choice of bonus features including a testing suite, advanced filtering, containerization and CI/CD prebuilt.
API
- Adaptive API allowing completely arbitrary depth of Channels/objects, see location:
popflix\contents\api
Channel rating command
-
Depth-first search algorithm to trace all nodes (Channel's ratings), summing them on each branch (superchannel) backtracking to root (origin Channel).
-
To run this management command, add below to terminal:
python manage.py channel_ratings
-
Warning : This command may differ depending on operating system, the command required could be python3 or py
Filtering
-
Category (Groups) options available to each superchannel that can be easily query filtered.
-
Add query statement below as suffix to active superchannel url:
?group=name_of_group
Testing suite
-
Unit testing accommodates all project features with test coverage of over 93%.
-
To run coverage tests, use this command in terminal:
coverage run --source='.' manage.py test
-
Coverage report available with command:
coverage report
These notes develop on the more interesting parts of the project
API
- To facilitate an arbitrary depth of Channels in the API, the final item in the URL is taken as the
key object and searched. The URL path is found retroactively by tracing parent Channels.
Filtering for Groups is achieved by checking for a
group
channel parameter.
API ListView
-
A generic view for listing Channels with several overrides.
-
Overridden dispatch method for handling URL validation and routing. Also handles the extraction of a
group
parameter from the GET request. -
The
get_queryset
method is overridden to provide a queryset that filters Channels based on achannel
or an optionalgroup
parameter.
-
API URL pattern:
-
URL pattern for the ListView with a dynamic path and optional
group
parameter.- This pattern captures a path and passes it to the ListView. The path here is the
hierarchy of Channels. The path is required, while the
group
is optional and can be omitted from the URL.
- This pattern captures a path and passes it to the ListView. The path here is the
hierarchy of Channels. The path is required, while the
API URL validator
-
A utility class for validating URLs against Channel and Content slugs.
- This class provides static methods to check the existence of Channels and Contents based on the slug and ensures that the URL matches the hierarchy of superchannels.
Channel rating command
-
A management command that calculates the average rating for each active Channel and its subchannels. It uses depth-first traversal to aggregate subchannel ratings and then calculates averages
Noteworthy methods:
handle
executes the command, calling "get_channel_ratings()" and writing the results to a csv file.get_channel_ratings
processes each Channel, sums subchannel ratings, calls "get_all_subchannels()".get_all_subchannels
performs an iterative depth-first traversal of a Channel hierarchy, collecting and returning all visited Channels and their aggregate ratings.
Channel model
-
Represents a Channel instance, object hierarchy and Group-Channel relationship set here.
Noteworthy fields:
groups
allows channels to be part of multiple Groups as it's set as a many-to-many relationship.superchannel
creates a hierarchical relationship between Channels as foreign key to another Channel/'self'
Noteworthy methods:
save
sets the slug and potentially updates related superchannels' Groups.get_all_superchannels
gets a list of all superchannels for a Channel.add_group_to_superchannels
adds the Channel's Groups to all of its superchannels.
ChannelManager
-
Custom model manager to retrieve and filter Channels.
get_channels_by_group
filters a given queryset of Channels by a group name.
- Python
- Python 3.11.0 - Used as base language.
- Django
- Django 4.2.8 - A Python web framework for rapid development.
- Django REST 3.14.0 - Django-based toolkit for building Web APIs.
- Database
- SQlite 3.38.4 - For a development database, provided by Django.
- Testing
- Coverage 7.4.0 - Code coverage measurement for Python.
- Docker
- Docker - Platform designed to help build, share, and run container applications.
- CI/CD
- GitHub Actions - Build, test, and deploy from your remote storage.
Please note - in order to run this project locally on your own system, you will need the following installed:
-
Clone the Popflix repository by either downloading from here or type the following command into your terminal:
git clone https://github.com/isntlee/PopFlix
-
Stay in your current folder, don't navigate into Popflix yet
-
A virtual environment is recommended for the Python interpreter. Enter the command:
python -m venv venv
- Warning : This Python command may differ depending on operating system, the command required could be python3 or py
- Navigate into Popflix and initialize the virtual environment by using the following command:
..\venv\Scripts\Activate.ps1
- Warning : This command may differ depending on your operating system
-
Install all the requirements and dependancies with the command:
pip install -r requirements.txt
-
Migrate the admin models to create your database template with the terminal command:
python manage.py migrate
-
Create your superuser to access the django admin panel and database with the following command:
python manage.py createsuperuser
-
Enter these details for the initial superuser. Ignore all warnings, don't add an email. Change the User password afterwards as this password is exposed. However, if you plan to add the prebuilt data below, you'll need these details to login, change User password after that.
Username = iam_the_law -- Password = 2000
-
You can now run the program locally with the following command:
python manage.py runserver
-
Once the program is running, go to localhost and add
/admin/
to the end of the url. Here log in with the initial superuser account. -
Create env.py file at root level where you can store your sensitive information for the app. Add these details to that file:
SECRET_KEY = "SECRET_KEY" DEBUG = "DEBUG"
-
Create a new and truly secret key, which will be generated in a secret_key.txt file at root level, with this command:
python core/generate_key.py
-
Find the SECRET_KEY and DEBUG variables in the core/settings.py file. You'll find two sets of SECRET_KEY and DEBUG variables: commented out and uncommented. You should comment out the uncommented, and vice-versa.
-
Finally, set the variables in your .env file. Set SECRET_KEY to the text found in secret_key.txt, remember to add '' as it should be a string. Set DEBUG to whatever you prefer, there are no security problems with DEBUG = 'True' in development. Do change for production.
-
If you would like to start with Channel/Content/User test data, then run this command:
python manage.py loaddata data/popflix_data.json
Please note - in order to run this container on your system, you will need Docker installed on your system. And, some working knowledge.
- Docker - to build and run this containerized application, add these commands to your terminal:
-
To build (if unbuilt) and start the container in detatched mode:
docker-compose up -d
-
To stop and remove the container:
docker-compose down
-
To use the relevant local deployment instructions above, prefix the commands with:
docker-compose exec web
- SQlite - For development database, provided by Django.
Users
The User model utilized for this project is the standard one provided by django.contrib.auth.models
Group model
Name | Key in DB | Validation | Field Type |
---|---|---|---|
Title | title | max_length=250 | CharField |
Active | active | default=True, null=True | BooleanField |
Picture Url | picture_url | max_length=250, null=True, blank=True | URLField |
Slug | slug | max_length=250, unique=True, null=True, blank=True | SlugField |
Channel model
Name | Key in DB | Validation | Field Type |
---|---|---|---|
Title | title | max_length=250 | CharField |
Language | language | max_length=250 | CharField |
Active | active | default=True, null=True | BooleanField |
Picture Url | picture_url | max_length=250, null=True, blank=True | URLField |
Groups | groups | blank=True | ManyToManyField |
Slug | slug | max_length=250, unique=True, null=True, blank=True | SlugField |
Superchannel | superchannel | on_delete=models.SET_NULL, null=True, blank=True | ForeignKey |
Content model
Name | Key in DB | Validation | Field Type |
---|---|---|---|
Name | name | max_length=250 | CharField |
Metadata | metadata | null=True, blank=True | JSONField |
File Url | file_url | max_length=250 | URLField |
Active | active | default=True, null=True | BooleanField |
Slug | slug | max_length=250, unique=True, null=True, blank=True | SlugField |
Rating | rating | MinValueValidator(0), MaxValueValidator(10) | DecimalField |
Channel | channel | on_delete=models.SET_NULL, null=True, blank=True | ForeignKey |