Skip to content
Snippets Groups Projects

SMart SCHeduling

coverage report

Docker version

If you'd like to try out the application without preparing the environment, you can use Docker (you must have Docker and docker-compose installed):

# Navigate to the project's directory
docker-compose build && docker-compose up
# To add a new user, type in the new terminal:
docker-compose exec web sh
python manage.py createsuperuser

Required software (on ubuntu's OS family):

  • sudo apt-get install libpq-dev python-dev postgresql postgresql-contrib python virtualenv python-virtualenv gcc python-lxml libxml2-dev libcurl4-openssl-dev libcurl4-gnutls-dev libgnutls28-dev

Postgres installation

Developer project installation

  • mkdir -p ~/dev/smash

  • cd ~/dev/smash

  • git clone ssh://git@git-r3lab-server.uni.lu:8022/NCER-PD/scheduling-system.git

  • cd scheduling-system

  • virtualenv env to create new virtualenv (contains clean python working environment)

  • . env/bin/activate (to start using virtualenv)

  • pip install -r requirements.txt to install project's dependencies

  • Create local_settings.py file in (./scheduling-system)/smash/smash directory by copying the template in (./scheduling-system)/smash/smash/local_settings.template and edit your local_setttings.py file to change your database connection data.

  • Update migration db scrpit from file structure (./scheduling-system/smash/manage.py makemigrations)

  • Create the database by applying migrations (./scheduling-system/smash/manage.py migrate)

  • Create the first, administrative, user- (./scheduling-system/smash/manage.py createsuperuser)

Development

  • Remember, that before working you have to activate virtualenv, by: devel@host ~/home/smash/scheduling-system $ . env/bin/activate
  • In order to run development server, run: devel@host ~/home/smash/scheduling-system/smash $ ./manage.py runserver and go to 127.0.0.1:8000 in browser
  • For reference of HTML tempalte, see https://almsaeedstudio.com/themes/AdminLTE/pages/widgets.html#

Mac Developers

In case of problems with the openssl version installed on the system:

export PYCURL_SSL_LIBRARY=openssl
pip install pycurl --global-option=build_ext --global-option="-I/usr/local/Cellar/openssl/1.0.2k/include" --global-option="-L/usr/local/Cellar/openssl/1.0.2k/lib" --upgrade
pip install psycopg2 --global-option=build_ext --global-option="-I/usr/local/Cellar/openssl/1.0.2k/include" --global-option="-L/usr/local/Cellar/openssl/1.0.2k/lib" --upgrade

Production deployment

  • git pull and other project installation should be performed in a dir where this django app should be installed, in this tutorial it's /var/www/scheduling-system/
  • install nginx: apt-get install nginx
  • create gunicorn service in systemd (http://docs.gunicorn.org/en/stable/deploy.html#systemd):

/etc/systemd/system/gunicorn.service

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
PIDFile=/run/gunicorn/pid
User=www-data
Group=www-data
WorkingDirectory=/var/www/scheduling-system/smash

ExecStart=/var/www/scheduling-system/env/bin/gunicorn --pid /run/gunicorn/pid smash.wsgi --error-logfile /var/log/gunicorn.log --log-level DEBUG --capture-output --limit-request-line 8192
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Don't forget to change ownership of /run/gunicorn/ folder and /var/log/gunicorn.log file.

chown -R www-data:www-data /run/gunicorn/
touch /var/log/gunicorn.log
chown www-data:www-data /var/log/gunicorn.log

/etc/systemd/system/gunicorn.socket

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn/socket
ListenStream=0.0.0.0:9000
ListenStream=[::]:8000

[Install]
WantedBy=sockets.target
  • modify nginx configuration

/etc/nginx/nginx.conf

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
        worker_connections 768;
        # multi_accept on;
}
http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;
        gzip_disable "msie6";

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

/etc/nginx/sites-enabled/default

upstream app_server {
    # fail_timeout=0 means we always retry an upstream even if it failed
    # to return a good HTTP response

    # for UNIX domain socket setups
    server unix:/run/gunicorn/socket fail_timeout=0;

    # for a TCP configuration
    # server 192.168.0.7:8000 fail_timeout=0;
}

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        listen 443 ssl;


        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name prc.parkinson.lu;

        ssl_certificate /etc/nginx/ssl/nginx.crt;
        ssl_certificate_key /etc/nginx/ssl/nginx.key;


        #configuration for static and media files hosted by nginx
        location /media/ {
                root /var/www/scheduling-system-files;
        }

        location /static/ {
                root /var/www/scheduling-system-files;
        }


        location / {
              # checks for static file, if not found proxy to app
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              # enable this if and only if you use HTTPS
              # proxy_set_header X-Forwarded-Proto https;
              proxy_set_header Host $http_host;
              # we don't want nginx trying to do something clever with
              # redirects, we set the Host: header above already.
              proxy_redirect off;
              proxy_pass http://app_server;
    }

}
  • extract static files and make them available via nginx: ./manage.py collectstatic
  • you start application by starting gunicorn and nginx: service gunicorn start, service nginx start

Cron jobs (weekly emails)

If weekly emails are required then cron must be edited to fire periodically django function that send emails.

> crontab -e
SHELL=/bin/bash
*/30 * * * * source /var/www/scheduling-system/env/bin/activate && python /var/www/scheduling-system/smash/manage.py runcrons >> /var/log/django-cronjob.log 2>&1

Operations

Disable two steps authentication for a specific user

./manage.py two_factor_disable ${USERNAME}

Public holidays

to import public holidays run:

./manage.py holidays ${YEARS}

where ${YEARS} should be a space separated list of years for which the holidays will be imported.

example:

./manage.py holidays 2017 2018 2019