/python3-django-qoqa

concept to package django projects as debian packages

Primary LanguagePythonGNU General Public License v3.0GPL-3.0

Django Qoqa 1.0

Django-qoqa is a command-line application to create Django's projects and to package them as Debian packages.

  • Qoqa is a Zulu word which roughly translates to 'to collect'.

This project is mainly a concept but can used to test the idea

This application is intended for simple traditional Django projects that don't require complex setups or deployments.

How to install django-qoqa

Since this project involves some debian tools and commands, the best way to use it is to install it as a debian package, that way it will install all necessary debian packaging tools.

Prebuilt

You can get the ready made .deb package here, if you don't want to build it yourself.

Source

if you want to build this package from source

  • Clone this repo

  • dpkg-buildpackage -us -uc

  • sudo dpkg -i python3-dajngo-qoqa_1.0.0_amd64.deb

Since this debian package is installed via dpkg and not via apt, dependencies will not be automatically installed, so the initial setup will fail, to install the remaining dependencies run this

  • sudo apt -f install

Tutorial

First create a top level directory for you project, this directory will contain the django project ,the virtual environment and other files that will be needed to build a debian package later on.

django-qoqa new fruit

where fruit is the name of the django project

The above command will launch an interactive session asking a couple of questions

[qoqa] Configuring New Django Project
Available django versions
1 - 2.2 LTS
2 - 3.1
[qoqa] select django version number [1]: 

This allows you to select a django version, this wil show the currently supported django versions.

Available Databases
1 - sqlite3
2 - postgresql
Development Database [1]: 

Production Database[1]:
1 - sqlite3
2 - postgresql

The supported databases are SQLite3 and PostgreSQL.

If you select PostgreSQL you'll be asked questions about the database such as database name, port, username etc.

The assumption is that you already know these details for this small project.

The production settings will be saved in a configuration file (production.cfg) with some production settings already there such as secret key and debug status.

Once you have entered the relevant details, the default packages will be installed:

  • Django
  • Whitenoise
  • Gunicorn
  • Django-debug-toolbar

Project Layout

Once you have created the project the folder structure will look as follows

|-- fruit
	|-- env3
	|-- production.cfg
	|-- fruit
		|-- manage.py
		|-- fruit
			|-- settings.py
			|-- etc
		|-- fruit.cfg

The production.cfg contains the config settings for production.

The fruit.cfg is the configuration file that is used during development

This is an example as to how the fruit.cfg file will look

[STATUS]
PRODUCTION = False

[SECRET_KEY]
VALUE = "$2[Qt8a_|j+kqF-2kdbn8ii4qn)?n8\gSXr$jHA)E[ga2]`uX

[DEVELOPMENT_DATABASE]
DATABASE = sqlite3
NAME = development_db.sqlite3

[ALLOWED_HOSTS]
HOSTS = localhost

The production.cfg file looks somewhat similar to the fruit.cfg file, just that production will be set to True and the secret key value will be different.

The fruit/settings.py file has been modified to accommodate the fruit.cfg file.

The modified fruit/settings.py is created via the django startproject template argument

At this point django-qoqa has done its job in creating the project. After this step django-qoqa is no longer involved with the django project until you need to package the project as a debian package.

So lets create a couple of django applications via the manage.py file (Don't forget to activate your virtual environment)

./manage.py startapp apple
./manage.py startapp banana

Building the Django Project

So after some development, creating views, adding static files, now its time to build the project

First we'll need create a requirements.txt file

$pip freeze -l > requirements.txt

This file needs to sit in the top level directory, same directory containing env3

$django-qoqa prepare --version 0.1.0

This command needs to be run in the top level directory, same directory containing env3

The above command will generate the required files needed to begin the build process.

This is how the top level directory looks like after the build process

|-- fruit
	|-- env3
	|-- debian
	|-- production.cfg
	|-- MANIFEST.in
	|-- requirements.txt
	|-- setup.py
	|-- fruit
		|-- apple
		|-- banana
		|-- __init__.py
		|-- etc

Debian directory

The debian directory contains the following files:

  • changelog - contains documentation about all the changes made to the package.
  • compat - sets he compatibility level of the build.
  • control - contains details about the project eg: Descriptions, dependencies etc.
  • fruit.service - This is a systemd unit file that will run the django project as a service.
  • postinst - This file contains details about what should happen after a package has been installed.
  • rules - This files contains the instructions as to how to build the package.
  • postrm - This file contains the details to remove the project once done

If you want to read more about the debian directory and what type of files can be placed in here, you can read this guide packaging for debian is a bit involved so the basic configurations have been created to make things easier.

Setup.py

This is how the default file will look

from setuptools import setup, find_packages

PACKAGE_DATA = {}

setup(
    name='fruit',
    version='0.1.0',
    packages=find_packages(),
    package_data=PACKAGE_DATA,
    # This is the data specified in the MANIFEST.in
    include_package_data=True,
)

The find_packages() function searches for all python packages that's why the __init__.py is there under the fruit directory.

We are treating the entire django project as a python package, allowing for the apple and banana apps to fall under the fruit package.

The PACKAGE_DATA dictionary is used to collect all the static files (*.css, *.js, *.djhtml) from the django apps.

So it will look like the following.

PACKAGE_DATA = {
	'fruit': [
		'apple/static/apple/css/*.css',
		'apple/static/apple/js/*.js'
		'apple/templates/apple/*.djhtml',
		'banana/templates/banana/*.djhtml',
		'banana/static/banana/css/*.css',
		'banana/static/banana/js/*.js'
		etc........
		
	]
}

More details about the setup.py file and configurations can be found here

Manifest.in

In the manifest file allows you to add any other data files to be included in your python package. In this case it will contain a start_gunicorn script, this will be used by the projects systemd unit file to start and stop the project.

Releasing the django project

So all the above files and directory (manifest,setup, debian) can be configured to suit your needs, the main idea behind this project is that you wont have to make any configuration changes or minimal ones. We are now ready to create a .deb file

$django-qoqa build --version 1.0.0

The debian/changelog file will open up allowing you to make any final changes. Underneath, build runs

dpkg-buildpackage -us -uc

The whole building process and .deb creation is created by dh-virtualenv

From the dh-virtualenv github page

dh-virtualenv is a tool that aims to combine Debian packaging with self-contained virtualenv based Python deployments.

Installing the .deb package

Once the build process is complete a fruit_0.1.0.deb file will be created.

To install the package

$sudo dpkg -i fruit_0.1.0.deb

This will install the package in

/opt/venvs/fruit/

To start the application

$systemctl start fruit

The production.cfg file needs to be renamed to the projects name so in this tutorial fruit.cfg

The application should now be running on 0.0.0.0:8000

Just to reiterate this is just a concept project. I wanted to see if it is possible to debianize a django project and what it would involve in making it work.