Django

Python Web/Database Applications

Web/Database applications have to do with responding to a browser request, processing information (from database and other), and generating a dynamic response based on the computation. There are three parts identified in this operation: Every Web/Database application has these aspects. What a web framework does is provide the structure for creating such application in which the M-V-C components are abstract and independent of each other as much as possible. The outcome is that the web framework structure provides: A language like Php is well suited to serving both roles: the controller classes and the template language. In contrast, Python is very well-suited to being the creating controller classes, but poorly suited for serving as a template language. There are other Python-based web frameworks such as Zope and CherryPy. All these frameworks use Python to define the controller classes and support a separate template script language to generate the views.

Django

Install Django and the Python MySQL package:
$ sudo apt install python3-django python3-pymysql
Verify the version you are using by running:
$ python3 -m django version
The Django site provides excellent documentation and tutorials:
https://docs.djangoproject.com/en/1.11/
The 7-part tutorial on Django is a recommended way to learn it. The thing to remember is that you have to consistently substitute "python3" for the document's usage of "python."

This document is written for Django version 1.11. When you look for Django documentation, make sure that you the docs version matches the version you're using because there are significant version differences.

Eclipse PyDev Re-configuration

Because of the Django Python software additions, we need to reset PyDev's PYTHONPATH environment variable. Go to Window ⇾ Preferences and select
PyDev ⇾ Interpreters ⇾ Python Interpreter
Click Apply to activate. A popup window asks for:
Select interpreters to be restored
 python3 (/usr/bin/python3)

Click OK to rebuild and then OK to leave.

PyDev vs. shell usage

Other than the very first step, we will make use of Eclipse PyDev as the IDE of choice for creating Django applications. However, Django provides shell-based tools for creating and manipulating its projects and any editor will work fine.

The choice for describing things by shell commands is that it is IDE-independent, and ultimately simpler. However, PyDev offers extra support to make things convenient, in particular, for running the development web server.

Create a Django Project

Django considers a project to be a "site," suggesting that it is the basis of one or more possibly-related web apps. Our site name is "appsite," named so as to avoid conflict with "mysite" used in the Django tutorial.

Although a Django project can be created from PyDev, doing so adds an extra top level with the same project name, making the whole thing unnecessarily complex and out-of-sync with what is done in the shell.

Run this shell command to create the appsite project.
$ cd ~/eclipse-workspace
$ django-admin startproject appsite  
After creation, we want to make a PyDev project from the existing code. To complete the installation, right-click on the appsite project and select Properties.

Select PyDev - Django. You should see:
Django manage.py    
Replace it by:
Django manage.py    

Initial layout and configuration

The files you'll see within the Django appsite project created are:
appsite/     (project line: most menu commands executed here)
  manage.py
  appsite/
    __init__.py    (indicates a Python package)
    settings.py
    urls.py
    wsgi.py

Change these timezone features

Python will want to use UTC to set time stamps. We want local time, so make these changes:

appsite/settings.py
TIMEZONE = "America/New_York"
...
USE_TZ = False

Run the development server

Django provides a fully-compliant HTTP 1.1 web server which is used to run its applications. As preparation for running:
$ cd ~/eclipse-workspace/appsite  
$ python3 manage.py migrate
To run the server from PyDev, simply click on the appsite project line and select
Run As ⇾ 1 PyDev: Django
The Console window you should see information:
...
Django version 1.11.11, using settings 'appsite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
View the development server Open a web browser to this URL:

Running the development server from the shell

  This subsection is just for reference.   The shell equivalent of what we have just done is:
--- in ~/eclipse-workspace/appsite ----
$ python3 manage.py runserver
Running the server will block the shell. One of the issues of running it this way is that for some changes you make, you have to stop (Control-C) and restart the server to pick them up. In contrast, when run through PyDev, the server is restarted as necessary.

Create the blog app

The PyDev project structure provides menu-driven capabilities to do the various creations and modifications to the project structure through a dedicated Django menu accessible from the project.

Right-click on the project, select
Django ⇾ Create application (manage.py startapp)
This brings up a dialog window:
App Name
Name of the django app to be created:
blog
Name cannot be empty
Click OK.

The newly created files and folders constitute this Python package:
blog/
  migrations/
  __init__.py
  admin.py
  models.py
  tests.py
  views.py
  db.sqlite3
This package is at the same level as the appsite package, the full Django project structure now looks like this:
appsite/
  manage.py
  appsite/
    ...
  blog/
    ...

App creation from the shell

  Again, this is the shell equivalent, which has already been done.   To create the blog app run this:
--- in ~/eclipse-workspace/appsite ----
$ python3 manage.py startapp blog
If you're working in Eclipse as well, refresh the appsite project to pick up the additions.

Create the initial blog app features

Edit blog/views.py, adding this initial content after the "Create your views here" comment line:

blog/views.py (appended)
from django.http import HttpResponse
 
def index(request):
    return HttpResponse("The blog index.")
select
Create a new file. Then enter this code:

blog/urls.py
from django.conf.urls import url
 
from blog import views   # or: from . import views
 
urlpatterns = [
    url(r'^$', views.index),
]
 
select
Edit appsite/urls.py. Look for the urlpatterns definition make this addition:

appsite/urls.py
from django.conf.urls import include  # add this line
 
urlpatterns = [
    ...
    url(r'^blog/', include('blog.urls')),  # add this line
]
This says that any URL starting with "blog" will be resolved in the blog.urls module.

View the development server Open a web browser to this URL:

Apache site access via ModWSGI

The aim of Apache Mod WSGI is to provide a simple module which can host any Python application which supports the Python WSGI interface. You should not use this WSGI access for site development. Keep the local site on port 8000; Apache must be reloaded to pick up any changes.

If you look at Django/WSGI documentation on the web, the docs indicate that the Python site is deployed in a virtual environment separate from the Python environment supplied by the operating system. This is possibly a better approach to avoid conflict with multiple WSGI sites, but it is unnecessary for our purposes.

Install and enable the relevant Apache modules
$ sudo apt install libapache2-mod-wsgi-py3
The installation should enable the wsgi Apache module.

Each Django project (site) that you want to make public should have its own Apache virtual host entry. We can easily create our own different hosts by using the loopback IP addresses 127.0.x.y with corresponding apache virtual host sites.

Create an entry in /etc/hosts:
127.0.1.2	appsite
Create the name virtual host site (make sure your login appears, not the generic "LOGIN"):

/etc/apache2/sites-available/appsite.conf
<VirtualHost appsite:80>
  WSGIScriptAlias / /home/LOGIN/eclipse-workspace/appsite/appsite/wsgi.py
 
  # This code is needed when you have multiple wsgi sites
  # The processGroup name choice must be different for each website.
  WSGIDaemonProcess appsite python-path=/home/LOGIN/eclipse-workspace/appsite
  WSGIProcessGroup appsite
 
  <Files wsgi.py>
    Require all granted
  </Files>
 
  # needed to realize the "/static" URL when appsite is used as host
  Alias /static /var/www/html/static
 
  # these are standard logging directives
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
select
Also edit the file
~/eclipse-workspace/appsite/appsite/settings.py
Make the change:
ALLOWED_HOSTS = [
  "appsite",
  "127.0.0.1",
]
Once we start prescribing the "Allowed Hosts", our development server localhost IP will get flagged unless this is added.

Then enable the newly-created site by:
$ sudo a2ensite appsite
and restart Apache to pick it up:
$ sudo systemctl reload apache2
With this in place you can test:
http://appsite/blog

Picking up editing changes

Make a simple change to the response generated in the blog/views.py file.

blog/views.py
from django.http import HttpResponse
 
def index(request):
    return HttpResponse("The blog index, modified.")
select
Then compare the development and Apache sites:
http://127.0.0.1:8000/blog
http://appsite/blog
You'll see that the development site has picked up the changes, but the Apache site has not. Then reload Apache:
$ sudo systemctl reload apache2
Now you'll see that the Apache site has picked up the changes.

Make /blog externally accessible

You want the proxy_http module installed:
$ sudo a2enmod proxy_http
Then modify the Apache default HTTP site:

/etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
  ProxyPreserveHost On
  ProxyPass  /blog   http://appsite/blog
  ...
</VirtualHost>
Reload Apache to pick up all changes:
$ sudo systemctl restart apache2
Make these changes in the settings.py module:
ALLOWED_HOSTS = [
  "appsite",
  "127.0.0.1",
  "MACHINE",
  "MACHINE.cs.wcupa.edu",
  "localhost",
]
Afterwards, you can use:
http://localhost/blog
http://MACHINE/blog
With the latter one, you can also access this /blog site from, say, a taz client external to your machine.

Tunnel access

If you're accessing MACHINE through the taz tunnel, this will also work:
http://localhost:2003/blog


© Robert M. Kline