(Draft)
[[TOC]]
!(To be written)!
- Python 3.8 (other versions of Python 3 may also be fine; one can specify the desired version in Pipfile)
- pipenv
Clone this repository with git clone or otherwise.
A Python virtual environment will be used, in which the Django package and other tools will be installed.
To install the Python packages used in this project, cd into the cloned repository and run:
pipenv install(For deployment, one may want to install the packages directly into the system; see the 'Deployment' section)
This will create a virtual environment and install into it Django, three other Python packages – django-upload-validator (used for file validation), requests (used for sending messages over webhooks) and psycopg2-binary (used for PostgreSQL; see the 'Database' section) – and any dependencies.
pipenv should print out where the virtual environment is installed (usually it is $HOME/.virtualenvs/<dir_name>-<hash>).
To activate the virtual environment:
pipenv shellWhen the virtual environment is active, its name should be displayed at the start of the prompt.
To exit the virtual environment, enter exit or press Ctrl + D.
Django works with various database backends, with official or third-party support. See Django's official documentation on databses.
The owner of the repository has opted for PostgreSQL.
To install the PostgreSQL software on the database host (with may or may not be the system where the Django project is developed/deployed), run:
sudo apt install postgresql (postgresql-contrib?)
For the Django project to work as PostgreSQL, one needs the Python package psycopg2-binary to be present in the virtual environment; see the package documentation.
This package depends on python3-dev and libpq-dev, which can be installed with APT.
To create and configure the database, enter PostgreSQL's psql prompt:
sudo -u postgres psqland run the following commands (replacing django, contest and password with custom values):
CREATE USER django WITH ENCRYPTED PASSWORD 'password';
ALTER ROLE django SET client_encoding TO 'utf8';
ALTER ROLE django SET default_transaction_isolation TO 'read committed';
ALTER ROLE django SET timezone TO 'UTC';
CREATE DATABASE contest;
GRANT ALL PRIVILEGES ON DATABASE contest TO django;
Exit the psql prompt by entering the command \q.
!(Configuring the Django project)!
Text editors may have built-in support or optional extensions that enhance the experience of working with Python. Visual Studio Code is used as an example here.
To optimise the coding, linting and debugging experience in VS Code, install the Python extension for VS Code and modify the workspace settings so that VS Code detects and uses the Python environment (see official instructions). VS Code will then launch its integrated terminal in the virtual environment (when the Python extension is activated).
See offical instructions on configuring VS Code for Python linting. It appears that VS Code uses the Pylint and autopep8 packages for linting and the Rope package for code refactoring by default.
Pylint may not be entirely compatible with Django.
To fix this, use the pylint-django plug-in, and modify the 'Pylint Args' setting in the workspace to include --load-plugins=pylint_django.
To install these development packages, simply run pipenv install --dev, as they have been specified in Pipfile.
!(Point to the official manual)!
django-admin startapp <app_name>
python3 manage.py makemigrations
python3 manage.py migrate
# To create an admin account:
python3 manage.py createsuperuserWith the virtual environment activated, run the following command and access localhost:8000 in a browser.
python3 manage.py runserver [<address>:<port>]If the project is on a remote server, then one can forward the port 8000 to a local machine via SSH.
Follow the offical instructions.
For deployment, clone this repository into a server, e.g. inside the home directory of a user named "django", and install the Python packages to the system:
pipenv install --system --deploy --ignore-pipfileSee the official deployment checklist.
Run the following command to copy static files into the path specified as STATIC_ROOT in the Django project settings.
python3 manage.py collectstaticThis section is based on the tutorial by Erin Glass. One important addition I have made is the inclusion of a file containing environment variables for deployment. The tutorial also contains debugging tips, which are omitted here. I do not yet fully understand everything in this section.
Store new-line-separated variable assignments in a file on the server (e.g. .env).
Gunicorn will be referred to this file.
With the virtual environment activated, install Gunicorn:
pipenv install --system gunicornCheck that Gunicorn works with the project's WSGI module by running:
gunicorn <project_name>.wsgi(optional argument --bind <address>:<port>; if you have simply cloned this repository, the project name is "contest").
This should have a similar effect to running "python3 manage.py runserver [<address>:<port>]".
Create the file /etc/systemd/system/gunicorn.socket and populate it with:
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
Create the file /etc/systemd/system/gunicorn.service and populate it with the example content below (substituting the paths <project_directory>, <environment_file_path> and <virtual_environment_directory>, and replacing contest if you have used a different project name):
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=<user>
Group=www-data
WorkingDirectory=<project_directory>
EnvironmentFile=<environment_file_path>
ExecStart=<virtual_environment_directory>/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
contest.wsgi:application
[Install]
WantedBy=multi-user.target
Enable and start the Gunicorn socket:
sudo systemctl enable --now gunicorn.socketThe socket file /run/gunicorn.sock should now have been generated; check by running:
file /run/gunicorn.sockand expecting output:
/run/gunicorn.sock: socket
Install Nginx:
sudo apt install nginxCreate the file /etc/nginx/sites-available/<configuration_name> and populate it with e.g.
server {
listen 443 ssl;
server_name contest.icmathscomp.org;
client_max_body_size 2m;
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt {
alias /home/django/deployment/robots.txt;
access_log off;
log_not_found off; }
location /static/ {
root /home/django/deployment;
}
location /media/ {
root /home/django/deployment;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}Create a symbolic link:
sudo ln -s /etc/nginx/sites-available/<configuration_name> /etc/nginx/sites-enabled/Remove the default symbolic link (this was not mentioned in the tutorial but seemed necessary for things to work on my system):
sudo unlink /etc/nginx/sites-enabled/defaultTest the Nginx configuration for syntax errors by running:
sudo nginx -tRestart Nginx to effect the configuration:
sudo systemctl restart nginxThe website should now be available at the server's domain or IP address (don't forget to allow Nginx traffic through the firewall with the ufw utility).
See one approach here. For how to revoke SSL certificates issued with this approach, see here.
After changes to the Django project, effect the changes by running:
sudo systemctl restart gunicorn
After changes to the Gunicorn or Nginx configuration, !(complete the paragraph)!
See Google Search Central's documentation on this subject.