Simple Django Tutorial

Post Under Development


  1. Prerequisites
  2. Create a Project (Site)
  3. Hello App
  4. Contacts App

1. Prerequisites

  1. Installed Django 1.9+
  2. Above is Running on Python 3

2. Create a Project (Site)

N.B. Django conflates Project with Site.

Run django-admin startproject

Assume CODE_HOME stands for the directory where you’d like to store your code.

django-admin startproject mysite

Here’s the resulting file structure. N.B. The top directory, named mysite, CONTAINS a sub-directory with the SAME NAME, mysite.


Verify the Site

cd CODE_HOME/mysite
python runserver

You should see something like the following.

Performing system checks...

System check identified no issues (0 silenced).


Django version 1.9.5, using settings 'mysite.settings'
Starting development server at
Quit the server with CTRL-BREAK.

Browsing to you should see something like the following.

It worked!
Congratulations on your first Django-powered page.

3. Hello App

Let’s make a Hello app and call it “hello”.

N.B. We will run django-admin startapp NOT startproject.
Again, assume CODE_HOME stands for the directory where you “stored your code”.
Remember the resulting tree from startproject was as follows.


Run django-admin startapp

cd CODE_HOME/mysite 
django-admin startapp hello

Here’s the resulting tree.


Add hello to

We need to edit the Site file to tell Django our hello app exists. Add one line to CODE_HOME/mysite/mysite/ as shown.

# CODE_HOME/mysite/mysite/

# Application definition

    'hello',                     # add this line

Add hello to our Site file.

Add one line in urlpatterns to CODE_HOME/mysite/mysite/ as shown.

# CODE_HOME/mysite/mysite/


urlpatterns = [
    url(r'^hello/', include('hello.urls', namespace="hello")), # add this line

A Great Seed for Angular Material – Cordova Apps

A Great App Seed from Mario Aleo

Mario Aleo has published a GREAT App Seed for Cordova – Angular Material Apps on his GitHub Repository cordova-angular-angularMaterial-seed.

When i first encountered a reference to the seed here on stackOverflow, I said “This looks like EXACTLY what i need. It [the Repository Documentation] is VERY WELL EXPLAINED”.

Since then, in the space of just a few hours, I have used Mario’s seed to produce a running app on my tablet. Not only is the GitHub Repository documentation GREAT, but the code in the Mario’s seed is SUPERBLY READABLE. I will learn a lot from using your code, Mario. Thanks.

Also, Mario says that his work is based on AngularJS Best Practices: Directory Structure by Adnan Kukic (@kukicadnan).

Thanks to BOTH of you.

Love and peace,


Execute Shell Commands from a Python GUI App

GUI Execute Commands

Here’s my Python – TKinter App that takes a set of Shell Commands from a .json file and displays them for individual execution when a button is clicked. Write these frequently used commands once and let the GUI program remember their syntax.

Keep 3 files in the same directory:

  • The TKInter Program
  • config.json The Configuration Data
  • cmds.json The Initial Command Set


  • The TKInter Program File –
  • The Configuration Data File – config.json
  • The Initial Command Set – cmds.json
  • A Screenshot of the TKInter Program
  • A run log of the program

The TKInter Program File –

Here is the file.

# -*- coding: utf-8 -*-
import sys, os, time, subprocess, json, atexit

# if not('.' in sys.path): sys.path.append('.')
# from MyCommands import cmds

import Tkinter, tkFileDialog

class Theapp(Tkinter.Tk):
    def __init__(self,parent):

        # joe's init
        with open('config.json') as data_file:
            cfg_data = json.load(data_file)
        self.cfg_data = cfg_data 

        with open(cfg_data[0]['commandsf']) as data_file:
            cmds = json.load(data_file)
        self.cmds = cmds 

        atexit.register(self.on_exit) #

        # /joe's init

        self.parent = parent

    def on_exit(self):
            save the state that has been changed

        self.cfg_data[0]['workingd'] = self.cwd.get()

        print "self.cwd.get(): %s"%(self.cwd.get())
        print "self.cfg_data: %s"%(self.cfg_data)

        with open('config.json', 'w') as f:
            json.dump(self.cfg_data, f)

    def execute_cmd(self, rnum):
        ''' C:\1d\PythonPjs\subprocessPjs\executeCommandsPj\executeCommands\

        commandstring = self.cmd_entries[rnum].get()
        cwdpath = self.cwd.get()
        outstr = subprocess.check_call(commandstring, cwd=cwdpath, shell=True)  #  Convenience Function
        print outstr

    def bclick(self, rnum):
        def click():            
        return click

    def browse2cwd(self):   
            find "def askdirectory(self):"
        tkFileDiaOpt4Dir = {}
        tkFileDiaOpt4Dir['initialdir'] = self.cwd.get()
        tkFileDiaOpt4Dir['mustexist'] = False
        tkFileDiaOpt4Dir['parent'] = self
        tkFileDiaOpt4Dir['title'] = 'Browse to set CWD.'

        self.cwd.set( tkFileDialog.askdirectory(**tkFileDiaOpt4Dir) )

        print "browse2cwd:  self.cwd.get(): %s"%(self.cwd.get())

    def initialize(self):
        self.cwd = Tkinter.StringVar()

        self.grid()  # make this be a grid

        ### add the gui elements in here

        ## browse to working directory
        label = Tkinter.Label(self, text="Working Directory", fg="white",bg="blue")

        self.cwd_entry = Tkinter.Entry(self, width=80, textvariable=self.cwd)
        self.cwd_entry.grid(column=0,row=1,columnspan=2, sticky='W') #

        b = Tkinter.Button(self,text=u"Browse", command=self.browse2cwd)

        toprowscount = 2

        ## command row elements len == len(MyCommands.cmds)
        self.buttons = []
        self.cmd_entries = []
        for rnum, cmd in enumerate(self.cmds):

            label = Tkinter.Label(self, anchor="w",text=cmd['label'], fg="white",bg="blue")

            self.cmd_entries.append( Tkinter.Entry(self, width=60) )
            self.cmd_entries[-1].grid(column=1,row=rnum+toprowscount,sticky='EW'); self.cmd_entries[-1].insert(0, (cmd['cmd']+' '+ cmd['args']))

            b = Tkinter.Button(self,text=u"Ex%s"%(rnum), command=self.bclick(rnum))


        ## Finish up
        self.grid_columnconfigure(0,weight=1) # make resizable
        self.resizable(True,False)            # make resizable ONLY HORIZONTALLY

if __name__ == "__main__":
    app = Theapp(None)
    app.title('Gui Execute Comands')

The Configuration Data File – config.json

Here is the config.json file.

   "programd": "C:\\1d\\PythonPjs\\GUIpjs\\guiExecuteCommandPj\\guiExecuteCommand", 
   "commandsf": "C:\\1d\\PythonPjs\\GUIpjs\\guiExecuteCommandPj\\guiExecuteCommand\\cmds.json",  
   "configd": "C:\\1d\\PythonPjs\\GUIpjs\\guiExecuteCommandPj\\guiExecuteCommand", 
   "workingd": "C:/1d/CrossPlatformPjs/CordovaPjs/cordovaAngular00Pj/cordovaAngular00"

The Initial Command Set – cmds.json

Here is the (INITIAL) cmds.json file

  {"cmd": "cordova", "args": "run android", "label": "android build 4 device"}, 
  {"cmd": "cordova", "args": "emulate android", "label": "android build 4 emulation"}, 
  {"cmd": "dir", "args": "*", "label": "dir of working dir"}

A Screenshot of the TKInter Program

Here is a screenshot of the program.


A run log of the program

Here is a run log.

Note: if the user changed the working directory, on exit the new working directory will be saved in the config.json file.

browse2cwd:  self.cwd.get(): C:/1d/CrossPlatformPjs/Building Single Page Web Apps with AngularJS PJ
 Volume in drive C is Windows
 Volume Serial Number is F2FB-4810

 Directory of C:\1d\CrossPlatformPjs\Building Single Page Web Apps with AngularJS PJ

12/23/2015  09:58 AM    <DIR>          .
12/23/2015  09:58 AM    <DIR>          ..
12/23/2015  11:11 AM    <DIR>          zetc
               0 File(s)              0 bytes
               3 Dir(s)  900,352,217,088 bytes free
self.cwd.get(): C:/1d/CrossPlatformPjs/Building Single Page Web Apps with AngularJS PJ
self.cfg_data: [{u'programd': u'C:\\1d\\PythonPjs\\GUIpjs\\guiExecuteCommandPj\\guiExecuteCommand', u'commandsf': u'C:\\1d\\PythonPjs\\GUIpjs\\guiExecuteCommandPj\\guiExecuteCommand\\cmds.json', u'configd': u'C:\\1d\\PythonPjs\\GUIpjs\\guiExecuteCommandPj\\guiExecuteCommand', u'workingd': u'C:/1d/CrossPlatformPjs/Building Single Page Web Apps with AngularJS PJ'}]


Show jQuery Client info in web2py View

This web2py View shows jQuery Client Side Info

{{left_sidebar_enabled,right_sidebar_enabled=False,('message' in globals())}}
{{extend 'layout.html'}}

{{block head}}




{{if 'message' in globals():}}
<h3>{{=message + "hello 3"}}</h3>
<h3>width: <span id="width"></span>    height: <span id="height"></span></h3>

Get web2py Debugging Info

Get Debugging Info

Here’s a quick way to get debugging info (Mobile or NOT).

from gluon.contrib.user_agent_parser import mobilize
import datetime
def index():
""" Here's an easy web2py debugging action [mobile or NOT] """
response.flash = T("Welcome to web2py!")
m = str( +"\n"
m += str(request.user_agent()) +"\n"
m += "\n"
m += "Hi. We have skipped a line."
return dict(message=PRE(T(m)))

2015-12-03 19:47:23.762934
<Storage {'os': <Storage {'version': 'NT 10.0', 'name': 'Windows'}>, 'is_tablet': False, 'is_mobile': False, 'browser': <Storage {'version': '46.0.2490.86', 'name': 'Chrome'}>}>

Hi. Is next line.