python - gregg roetengreggroeten.com/pub-doc-soft/python-django-pycharm-designer-doc.pdfdjango (web...

65
pg 1 Python Django (Web Application Framework - WAF) PyCharm (Integration Development Environment - IDE) Compiled and condensed notes from various online sources Gregg Roeten

Upload: vuongnga

Post on 26-Mar-2018

256 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 1

Python

Django

(Web Application Framework - WAF)

PyCharm (Integration Development Environment - IDE)

Compiled and condensed notes from various online sources

Gregg Roeten

Page 2: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 2

Build Environment as of 09/10/2015

Windows 7

JetBrains PyCharm Community Edition 4.5.4 Build #PC0141.2569 Aug 28, 2015 JRE 1.8.0-51-b16x86 JVM: Java Hotspotserver Django 1.8.4 Python 3.4.3 Python SDKs, list of the interpreters available on your machine. PyCharm supports: Standard Python interpreters, IronPython, PyPy, Jython, Cpython Settings Project: MysiteProject Project Interpreter Package Version Latest Django 1.8 1.84 Pygments 2.0.2 2.0.2 pip 6.1.1 7.1.2 pudb 2015.2 2015.3 pytz 2015.2 2015.4 setuptools 15.2 18.3.1 urwid 1.3.0 1.3.0

Page 3: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 3

TABLE OF CONTENTS

PYTHON ............................................................................................ ERROR! BOOKMARK NOT DEFINED.

PYTHON GENERAL NOTES ..................................................................................................................... 6

PYTHON CODING STYLE FOR DJANGO............................................................................................. 9

Python style ........................................................................................................................................................................ 9

Template style ..................................................................................................................................................................... 9

View style ............................................................................................................................................................................ 9

Model style ......................................................................................................................................................................... 9

Use of django.conf.settings ............................................................................................................................................... 11

Miscellaneous ................................................................................................................................................................... 11

DJANGO .......................................................................................................................................................... 1

DJANGO WORKFLOW FOR URLS, TEMPLATES AND APPS ..................................................... 12

.......................................................................................................................................................................................... 12

DJANGO PROCESS FLOW - BRIEF ..................................................................................................... 13

PROCESS FLOW - DETAILED ............................................................................................................... 14

User requests a page - How does Django process a request? ........................................................................................... 14

Request reaches Request Middlewares .............................................................................................................................. 14

handler send dispatcher signal request_started ............................................................................................................... 14 handler’s _request_middleware ...................................................................................................................................... 14

ROOT_URLCONF .......................................................................................................................................................... 14 _view_middleware ......................................................................................................................................................... 15

Django template structure ............................................................................................................................................... 15 render template .............................................................................................................................................................. 15

view - create an instance of django.http.HttpResponse. ...................................................................................... 15 exception ....................................................................................................................................................................... 15 Still no HttpResponse ..................................................................................................................................................... 15

handler fires the dispatcher signal request_finished, ............................................................................................. 15

GIT SETUP ................................................................................................................................................... 16

Page 4: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 4

WSGI WEB SERVER GATEWAY INTERFACE .................................................................................. 17 urls.py and views.py....................................................................................................................................................... 17

M = Model = data ............................................................................................................................................................. 18

V = View = window on screen........................................................................................................................................... 18

C = Controller .................................................................................................................................................................. 18

CMS .................................................................................................................................................................................. 18

DATABASES ................................................................................................................................................ 19

SQLite............................................................................................................................................................................... 19 Substring matching and case sensitivity .......................................................................................................................... 19 Old SQLite and CASE expressions ................................................................................................................................. 20 Using newer versions of the SQLite DB-API 2.0 driver .................................................................................................. 20 “Database is locked” errors ............................................................................................................................................ 20 QuerySet.select_for_update() not supported.................................................................................................................... 20 “pyformat” parameter style in raw queries not supported ................................................................................................ 20 Parameters not quoted in connection.queries ................................................................................................................... 20

MODELS ....................................................................................................................................................... 22

Define Model .................................................................................................................................................................... 22

Using Models .................................................................................................................................................................... 22

ADMIN .......................................................................................................................................................... 23

View .................................................................................................................................................................................. 23

DJANGO - HOW TO START AND DESIGN WITH DJANGO.......................................................... 24

Normal Start Django ........................................................................................................................................................ 24

DB Web app - Setup ......................................................................................................................................................... 25

Configure and Create Database ....................................................................................................................................... 26

Create Python model ........................................................................................................................................................ 29

Synchronizing the Database ............................................................................................................................................. 30

Configuring the Admin Interface ..................................................................................................................................... 30

API.................................................................................................................................................................. 33

CUSTOMIZE USERS ................................................................................................................................. 36

Creating an admin user .................................................................................................................................................... 36

Customize admin form ..................................................................................................................................................... 36

TEMPLATES ............................................................................................................................................... 38 Web site /polls/34 ........................................................................................................................................................ 39

How to return an HttpResponse object............................................................................................................................ 40 How to differentiate the URL names between Multiple applications in a Django project .................................................. 41

Page 5: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 5

USE GENERIC VIEWS: LESS CODE IS BETTER ............................................................................. 44

Page 6: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 6

1. Why PyCharm

A. Python Code Editor

1. Syntax highlighting

2. auto indent, code reformat

3. code completion

4. go to declaration, find usages

5. code analysis, inspection

6. realtime error highlighting

7. Rename refactoring allows to perform global code changes safely and instantly. Local changes

within a file are performed in-place. Refactorings work in plain Python and Django projects.

8. Extract Method to break up longer methods, Extract Superclass, Push Up, Pull Down and

Move to move the methods and classes.

9.

B. Django IDE +JavaScript

1. IDE provides high-class capabilities for professional Web development with Django framework

and Google App Engine.

2. coding assistance, navigation

3. breakpoints inside Django templates. Stop web appl where you need

4. Javascript debugger

C. Run, Debug, Test

1. execute tasks from your manage.py file. Use 'Run manage.py task' action, enter a task name or

event part of it and select the one you need. Debugger is started the same way.

2. Test Your Code: a test file, a single test class, a method, or all tests in a folder.

3. Create setup.py quickly using a special dialog and easily launch tasks defined inside setup.py

4. Python testing frameworks: Unittest, Doctest, Nosetest, py.test and Attest.

5. embedded local terminal

6. version control integration, Mercurial, Subversion, Git, CVS

7. Univided UI

8. Customizable UI

9. Issue Trackers integration, GitHub tracker

10. Plugins

11. SQL support for (Django, Flask) etc, SQL statements into source code.

12. PyCharm does not enable you to create databases, but provides facilities to manage and query

them.

13. deployment servers-deploy your local applications to some remote server.

https://confluence.jetbrains.com/display/PYH/PyCharm+IDE+and+Python+Plugin+for+IntelliJ+IDEA

2. Deployment in PyCharm

Don’t be fooled “Deployment in PyCharm” is to deploy existing project on remote server. Upload project to a remote server. Running a copy on a separate server.

Page 7: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 7

Supported Languages

Python (Versions: 2.x, 3.x)

Jython

Cython

IronPython

PyPy

Javascript

CoffeScript

TypeScript

HTML/CSS

Django/Jinja2 templates

web2py templates

Chameleon templates

Gql

LESS/SASS/SCSS/HAML

Mako

Puppet

RegExp

Rest

SQL

XML

YAML

Frameworks & Libraries supported

Django

Flask

Google App Engine

web2py

Pyramid

wxPython, PyQt, PyGTK

SQLAlchemy

...

3. Python general notes Multithreading: No - single threaded: there are “threads”, but Global Interpreter Lock

(GIL) allows just one Python thread to execute at any given moment of time (except the case when one of threads awaits for IO completion).

everything is dynamic so Python doesn’t need generics.

dd your own “tags” (fields or methods) to nearly any object to change the behavior of third-party code.

Python’s decorators are definitely unbeatable in simplicity and flexibility.

use *args, **kwargs - for static languages to enumerate/pass call arguments.

“with” contexts in Python can process exceptions: __exit__ method there gets

Page 8: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 8

information about thrown exception.

Page 9: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 9

4. Python Coding style for Django

A. Python style

Use four spaces for indentation.

Use underscores, for variable, function and method names (i.e. poll.get_unique_voters(), not poll.getUniqueVoters).

Use InitialCaps for class names (or for factory functions that return classes).

Use convenience imports whenever available. For example, do this: from django.views.generic import View

Don’t do this:

from django.views.generic.base import View

B. Template style

In Django template code, put one (and only one) space between the curly brackets and the tag contents.

Do this:

{{ foo }}

Don’t do this:

{{foo}}

C. View style

In Django views, the first parameter in a view function should be called request.

Do this:

def my_view(request, foo):

# ...

Don’t do this:

def my_view(req, foo):

# ...

D. Model style

Field names should be all lowercase, using underscores instead of camelCase.

Do this:

class Person(models.Model):

first_name = models.CharField(max_length=20)

last_name = models.CharField(max_length=40)

Don’t do this:

class Person(models.Model):

FirstName = models.CharField(max_length=20)

Last_Name = models.CharField(max_length=40)

The class Meta should appear after the fields are defined, with a single blank line separating the fields and the class definition.

Do this:

class Person(models.Model):

first_name = models.CharField(max_length=20)

last_name = models.CharField(max_length=40)

class Meta:

verbose_name_plural = 'people'

Page 10: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 10

Don’t do this:

class Person(models.Model):

first_name = models.CharField(max_length=20)

last_name = models.CharField(max_length=40)

class Meta:

verbose_name_plural = 'people'

Don’t do this, either:

class Person(models.Model):

class Meta:

verbose_name_plural = 'people'

first_name = models.CharField(max_length=20)

last_name = models.CharField(max_length=40)

If you define a __str__ method (previously __unicode__ before Python 3 was supported), decorate the model class with python_2_unicode_compatible().

The order of model inner classes and standard methods should be as follows (noting that these are not all required):

All database fields

Custom manager attributes

class Meta

def __str__()

def save()

def get_absolute_url()

Any custom methods

If choices is defined for a given model field, define each choice as a tuple of tuples, with an all-uppercase name as a class attribute on the model. Example: class MyModel(models.Model):

DIRECTION_UP = 'U'

DIRECTION_DOWN = 'D'

DIRECTION_CHOICES = (

(DIRECTION_UP, 'Up'),

(DIRECTION_DOWN, 'Down'),

)

Page 11: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 11

E. Use of django.conf.settings

Modules should not in general use settings stored in django.conf.settings at the top level (i.e.

evaluated when the module is imported). The explanation for this is as follows:

Manual configuration of settings (i.e. not relying on the DJANGO_SETTINGS_MODULE

environment variable) is allowed and possible as follows:

from django.conf import settings

settings.configure({}, SOME_SETTING='foo')

However, if any setting is accessed before the settings.configure line, this will not work. (Internally,

settings is a LazyObject which configures itself automatically when the settings are accessed if it has not already been configured).

So, if there is a module containing some code as follows:

from django.conf import settings

from django.core.urlresolvers import get_callable

default_foo_view = get_callable(settings.FOO_VIEW)

...then importing this module will cause the settings object to be configured. That means that the

ability for third parties to import the module at the top level is incompatible with the ability to configure the settings object manually, or makes it very difficult in some circumstances.

Instead of the above code, a level of laziness or indirection must be used, such as

django.utils.functional.LazyObject,

django.utils.functional.lazy() or

lambda.

F. Miscellaneous

Mark all strings for internationalization;.

Remove import statements that are no longer used when you change code. flake8 will identify these imports for you. If an unused import needs to remain for backwards-compatibility, mark the end of with # NOQA to silence the flake8 warning.

Systematically remove all trailing whitespaces from your code as those add unnecessary bytes, add visual clutter to the patches and can also occasionally cause unnecessary merge conflicts. Some IDE’s can be configured to automatically remove them and most VCS tools can be set to highlight them in diff outputs.

Please don’t put your name in the code you contribute. Our policy is to keep contributors’ names in the AUTHORS file distributed with Django – not scattered throughout the codebase itself. Feel free to include a change to the AUTHORS file in your patch if you make more than a single trivial change.

Page 12: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 12

Django workflow for Urls, Templates and Apps

HttpRequest from user

Apps layer models.py and views.py in folder Application/template modifies content

MVC = View*

Templates layer DIRS TEMPLATES in settings.py files .html in templates/admin information layout MVC =View (Python definition*)

Database

Project uses SQLite could use MySQL, etc

MVC = Model

Use WSGI (Web Server Gateway Interface) wsgi.py

Dynamic info from customer

Static info from customer

urls layer

url resolution - uses regular expressions to route requests file urls.py in folders MysiteProject, Application/templates

MVC = Controller

Customer input PC Browser

HttpResponse to user

WSGI

Apache/ mod_python server, therefore Django handles

Page 13: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 13

5. Django process flow - brief 1. User requests a page, running on Apache/mod_python therefore Django handles

2. HttpRequest sent to Request Middlewares (request function) which could manipulate or answer the HttpRequest

3. If no answer, then resolve URL with ROOT URLCONF in settings.py, match = MysiteProject.urls and send view function.

4. If match, handler calls View Middlewares (view function), which could manipulate or answer the HttpRequest

5. The view function may access data through models, must return HttpResponse or exception.

6. All model-to-DB interactions are done via a manager

7. Views passed to the Template (base_site.html or index.html) for rendering

8. Template uses Filters and Tags (logic with html tags) to render the output

9. HttpResponse is sent to the Response Middlewares (get_response function)

10. The response is sent to the user’s browser.

For details of each step see below

Page 14: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 14

6. Process flow - detailed

A. User requests a page - How does Django process a request? If Apache/mod_python is the server setup, in which case the request is handed to Django by

mod_python creating an instance of django.core.handlers.modpython.ModPythonHandler.

The handler imports your Django settings file.

B. Request reaches Request Middlewares 4 possible actions process: request, view, response and exception.

_request_middleware is a list of the process_request methods (in each case these will be

the actual methods, so they are directly callable) from any middleware classes which

defined them.

_view_middleware is a list of the process_view methods from any middleware classes,

which defined them.

_response_middleware is a list of the process_response methods from any middleware

classes, which defined them.

_exception_middleware is a list of the process_exception methods from any middleware

classes, which defined them.

C. handler send dispatcher signal request_started

Then it instantiates a subclass of django.http.HttpRequest.

Once an HttpRequest of some sort exists, the handler calls its own get_response method,

passing the HttpRequest as the only argument.

handler’s _request_middleware

does is loop through the handler’s _request_middleware instance variable and call each

method in that list, passing in the HttpRequest instance as an argument.

get_response to return instance of django.http.HttpResponse, to handler’s _request_middleware

More commonly, though, the middleware methods applied here simply do some processing

and decide whether to add, remove or supplement attributes of the request.

D. ROOT_URLCONF

if Middlewares didn’t send a response, the handler next tries to resolve the requested URL.

It looks in the settings file for a setting called ROOT_URLCONF, and hands that, along with

a base URL of /, as arguments to create an instance of

django.core.urlresolvers.RegexURLResolver, then calls the RegexURLResolver‘s resolve

method with the requested URL path.

The URL resolver follows a simple pattern. For each item in the urlpatterns list generated by

the URL configuration file specified by the ROOT_URLCONF setting, it checks whether

the requested URL path matches that item’s regular expression; if so , there are

two options:

If the item has a call to include, the resolver chops off the bit of the URL that matched,

moves to the URL configuration file specified by the include and begins iterating over

the items in its urlpatterns list. Depending on the depth and modularity of your

URL hierarchy, this may be repeated several times.

Otherwise, the resolver returns three items: the view function specified by the matched

item, a list of non-named matched groups from the URL (to be used as positional

arguments for the view) and a dictionary of keyword arguments, built from a

combination of any named matched groups in the URL and any extra keyword

arguments specified in that line in the URLConf.

Page 15: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 15

If no matches are found, the resolver raises the exception

django.core.urlresolvers.Resolver404, a subclass of the exception django.http.Http404.

We’ll get to how that’s handled a little later on.

_view_middleware

knows the view function and what arguments to pass to it,

the handler looks at its _view_middleware list, and calls each method in that list, passing the

HttpRequest, the view function, the list of positional arguments for the view and the

dictionary of keyword arguments for the view.

Again, it’s possible for middleware to intervene at this stage and force the handler to

return immediately.

E. Django template structure

base_site.html extends admin/base_site.html, which is in PROJECT_DIR/template path

index.html extends admin/base_site.html, which is in

PROJECT_DIR/PoolsApplications/template path

render template

Loading the template to be rendered; is handled by the function

django.template.loader.get_template,

The get_template function returns an instance of django.template.Template, which is an

object containing the parsed template and methods for using it.

The return value of the Template‘s render method is a string, which is the concatenation of

the return values of the render methods of all the Template‘s constituent Nodes, called

in the order in which they occur in the Template.

F. view - create an instance of django.http.HttpResponse.

exception

get_response passing the HttpRequest and the exception as arguments.

one of those methods may instantiate and returns an HttpResponse.

Still no HttpResponse

The view might not have returned a value.

The view might have raised an exception that none of the middleware was able to deal with.

A middleware method that was trying to deal with an exception might have raised a new

exception itself.

Default get_response sends Http404

If DEBUG is False, page_not_found,

If the DEBUG setting is True, technical_500_response,

G. handler fires the dispatcher signal request_finished,

which is the absolute last call for anything that wanted to execute during the current request?

clean up

free any resources

Page 16: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 16

Git setup

create a working directory & navigate to it

$ mkdir custom-reg-tutorial

$ cd custom-reg-tutorial

download the git repo

# don't forget the . at the end!

$ git clone https://github.com/launchsaas/custom-reg-tutorial.

git for version control

GitHub for project management

1. GitHub's "Issues" for the following:

1. bug tracking

2. feature requests

3. planned features

4. release/version management

git-flow for git workflow

py.test for unit testing

https://www.jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/

Page 17: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 17

WSGI Web Server Gateway Interface

WSGI is the Web Server Gateway Interface. A specification describes how a web server communicates with web applications, and how web applications can be chained together to process one request.

WSGI is a Python standard

Use a Web app framework. They all support WSGI at this point, which means you need to worry about configuration and deployment of your app, and nothing else.

urls.py and views.py

focus on urls.py and views.py that will process your urls and return the info you want as an http response.

e.g. urls.py

urlpatterns += patterns ('myapp.views',

url (r'^getstuff/$', ‘getstuff’),

)

in views.py

def getstuff (request):

do whatever in python

return HttpResponse (stuff to return)

Page 18: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 18

Python’s web service framework is based on MVC

1. Django uses MVC (Model View Controller) MVC (Model View Controller) used as the Design pattern, for definitions see below.

different from standard MVC definition

Framework itself, mechanism that sends a request to the appropriate view

M = Model = data

Database layer

Encapsulates application state

Responds to state queries

Notifies view of changes

V = View = window on screen

Different Django View and standard MVC view

selects which data to display and how to display it

renders the models

Requests updates

Allows controller to select view

handled by views.py and templates directory

C = Controller

Defines application behavior, based on user input, access model as needed

by following the URLConf and calling the appropriate Python function for the given URL

Isolates logic (Model) from the user interface(View)

CMS

Django is not a CMS, or any sort of “turnkey product” in and of itself. It’s a Web framework; it’s a programming tool that lets you build Web sites.

Django version Python versions 1.4 2.5, 2.6, 2.7 1.7, 1.8 2.7 and 3.2, 3.3, 3.4 1.9 2.7, 3.3, 3.4, 3.5

Page 19: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 19

2. Databases

You don't need to use database in Django projects. Django comes with some standardized architecture that follows MVC pattern (or MVT as sometimes described). This includes models, views, url dispatching, templates, etc.

Probably you need to do following things to accomplish your task:

create url definition in urls.py to some Django view

write Django view that call somehow your API and displays result as a web page

you don't need models and database at all

Small project usually consists of the web server and "back-end" code will run on the same system (initially, Windows system) as the UI.

creation of a basic poll application.

It’ll consist of two parts:

A public site that lets people view and vote in them.

An admin site that lets you add, change and delete polls.

If you plan to use Django’s manage.py migrate command to automatically create database tables for your models (after first installing Django and creating a project), you’ll need to ensure that Django has permission to create and alter tables in the database you’re using; if you plan to manually create the tables, you can simply grant Django SELECT, INSERT, UPDATE and DELETE permissions. After creating a database user with these permissions, you’ll specify the details in your project’s settings file, see DATABASES for details.

If you’re using Django’s testing framework to test database queries, Django will need permission to create a test database.

H. SQLite

SQLite provides an excellent development alternative for applications that are predominantly

read-only or require a smaller installation footprint. As with all database servers, though, there

are some differences that are specific to SQLite that you should be aware of.

Substring matching and case sensitivity

For all SQLite versions, there is some slightly counter-intuitive behavior when attempting to

match some types of strings. These are triggered when using the iexact or contain filters in Querysets. The behavior splits into two cases:

1. For substring matching, all matches are done case-insensitively. That is a filter such as

filter (name__contains="aa") will match a name of "Aabb".

2. For strings containing characters outside the ASCII range, all exact string matches are

performed case-sensitively, even when the case-insensitive options are passed into the query.

Therefore, the iexact filter will behave exactly the same as the exact filter in these cases.

Some possible workarounds for this are documented at sqlite.org, but they aren’t utilized by

the default SQLite backend in Django, as incorporating them would be fairly difficult to do

robustly. Thus, Django exposes the default SQLite behavior and you should be aware of this when doing case-insensitive or substring filtering.

Page 20: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 20

Old SQLite and CASE expressions

SQLite 3.6.23.1 and older contains a bug when handling query parameters in a CASE

expression that contains an ELSE and arithmetic.

SQLite 3.6.23.1 was released in March 2010, and most current binary distributions for

different platforms include a newer version of SQLite, with the notable exception of the Python 2.7 installers for Windows.

Using newer versions of the SQLite DB-API 2.0 driver

Django will use a pysqlite2 module in preference to sqlite3 as shipped with the Python

standard library if it finds one is available.

This provides the ability to upgrade both the DB-API 2.0 interface and SQLite 3 itself to

versions newer than the ones included with your particular Python binary distribution, if needed.

“Database is locked” errors

SQLite is meant to be a lightweight database, and thus can’t support a high level of

concurrency. OperationalError: database is locked errors indicate that your application is

experiencing more concurrency than SQLite can handle in default configuration. This error

means that one thread or process has an exclusive lock on the database connection and

another thread timed out waiting for the lock the be released.

Python’s SQLite wrapper has a default timeout value that determines how long the second

thread is allowed to wait on the lock before it times out and raises the OperationalError: database is locked error.

If you’re getting this error, you can solve it by:

Switching to another database backend. At a certain point SQLite becomes too “lite” for

real-world applications, and these sorts of concurrency errors indicate you’ve reached

that point.

Rewriting your code to reduce concurrency and ensure that database transactions are

short-lived.

Increase the default timeout value by setting the timeout database option: 'OPTIONS': {

# ...

'timeout': 20,

# ...

}

This will simply make SQLite wait a bit longer before throwing “database is locked” errors; it won’t really do anything to solve them.

QuerySet.select_for_update() not supported

SQLite does not support the SELECT ... FOR UPDATE syntax. Calling it will have no effect.

“pyformat” parameter style in raw queries not supported

For most backends, raw queries (Manager.raw() or cursor.execute()) can use the “pyformat”

parameter style, where placeholders in the query are given as '%(name)s' and the parameters are passed as a dictionary rather than a list. SQLite does not support this.

Parameters not quoted in connection.queries

sqlite3 does not provide a way to retrieve the SQL after quoting and substituting the

parameters. Instead, the SQL in connection.queries is rebuilt with a simple string

Page 21: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 21

interpolation. It may be incorrect. Make sure you add quotes where necessary before copying a query into an SQLite shell.

Page 22: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 22

3. Models single, definitive source of information about your data.

contains

essential fields

behaviors of the data you’re storing.

model maps to a single database table.

A. Define Model

ex. application named polls, contains file models.py

This example model defines a Person, which has a first_name and last_name:

from django.db import models

class Person(models.Model):

first_name = models.CharField(max_length=30)

last_name = models.CharField(max_length=30)

first_name and last_name are fields of the model.

Each field is specified as a class attribute,

each attributes maps to a database column.

model would create a database table like this:

CREATE TABLE myapp_person (

"id" serial NOT NULL PRIMARY KEY,

"first_name" varchar(30) NOT NULL,

"last_name" varchar(30) NOT NULL

);

B. Using Models

Tell Django how to use models

mysite\mysite\settings.py

function INSTALLED_APPS

add name of module that contains your models.py

ex ‘polls’,

run manage.py migrate

run manage.py makemigrations

C. Fields

Example: polls\models.py file

from django.db import models

class Musician(models.Model):

first_name = models.CharField(max_length=50)

Page 23: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 23

last_name = models.CharField(max_length=50)

instrument = models.CharField(max_length=100)

class Album(models.Model):

artist = models.ForeignKey(Musician)

name = models.CharField(max_length=100)

release_date = models.DateField()

num_stars = models.IntegerField()

4. Admin

Select an object then change it

let’s you write and register actions, simple functions that get called with a list of objects

A. View

All Django wants is that HttpResponse. Alternatively, an exception.

Each view is responsible for doing one of two things:

returning an HttpResponse object containing the content for the requested page, or

raising an exception such as Http404. The rest is up to you.

Your view can

read records from a database, or not.

use a template system such as Django’s – or

a third-party Python template system – or not.

generate a PDF file,

output XML,

create a ZIP file on the fly,

anything you want, using whatever Python libraries you want.

view is a “type” of Web page in your Django application that generally serves a specific function

and has a specific template. For example, in a blog application, you might have the following views:

Blog homepage – displays the latest few entries.

Entry “detail” page – permalink page for a single entry.

Year-based archive page – displays all months with entries in the given year.

Month-based archive page – displays all days with entries in the given month.

Day-based archive page – displays all entries in the given day.

Comment action – handles posting comments to a given entry.

In our poll application, we’ll have the following four views:

Question “index” page – displays the latest few questions.

Question “detail” page – displays a question text, with no results but with a form to vote.

Question “results” page – displays results for a particular question.

Vote action – handles voting for a particular choice in a particular question.

In Django, web pages and other content are delivered by views. Each view is represented by a

simple Python function (or method, in the case of class-based views). Django will choose a view

by examining the URL that’s requested (to be precise, the part of the URL after the domain name).

Page 24: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 24

Python - 2 methods to start and design with Python

Method 1

Use wordpad for editing .py files

Use Windows command prompt to run python commands, like server, etc

Method 2 - PyCharm Preferred method

PyCharm background and setup

PyCharm supports Django including

Dedicated project type

ability to run tasks from the manage.py utility

Django templates support (syntax and error highlighting, code completion, navigation, completion for block names, resolve and completion for custom tags and filters, and quick documentation for tags and filters).

Ability to create templates from usage.

Ability to debug Django templates.

Live templates (snippets) for the quick development of Django templates.

Run/debug configuration for Django server.

Navigation between views and templates.

Code insight support for Django ORM.

Code completion and resolve in

Start JetBrains - PyCharm Community Edition 4.0.6

Open project

Page 25: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 25

Normal Start for Django in PyCharm

open Terminal part of window and startup server

python manage.py runserver

project directory has manage.py

Django Python web server address http://127.0.0.1:8000/

DB Web app - Setup python -c "import Django; print(django.get_version())"

Python 3.3 latest release, Django 1.7, 1.8 is beta

Page 26: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 26

django-admin startproject mysite creates project mysite and directory structure

mysite/

manage.py

mysite/

__init__.py

settings.py

urls.py

wsgi.py

File Definitions in the Project view

mysite directory is a container for your project. In the Project view it is denoted with

bold font.

manage.py: This is a command-line utility that lets you interact with your Django

project.

The nested directory mysite is the actual Python package for your project.

mysite/_init_.py: This empty file tells Python that this directory should be considered a

Python package.

mysite/settings.py: This file contains configuration for your Django project.

mysite/urls.py: This file contains the URL declarations for your Django project. a

“table of contents” of your Django-powered site.

mysite/wsgi.py: This file defines an entry-point for WSGI-compatible web servers

to serve your project. See Appendix How to deploy with WSGI for more details.

polls/models.py: In this file, we'll create models for our application.

polls/views.py: In this file, we'll create views.

templates directory is by now empty. It should contain the template files.

The nested directory migrations contains by now only the package file _init_.py, but

will be used to propagate the changes you make to your models (adding a field, deleting a

model, etc.) into your database schema. Read the migrations description here.

Always remember we have two mysites, designated “inner” and “outer”

The outer mysite/ root directory is just a container for your project. rename it to anything

you like.

The inner mysite/ directory are the actual Python package for your project. Used to import anything inside it (e.g. mysite.urls).

Configure and Create Database edit mysite/settings.py

select the project tool window and press F4.

select DATABASES var click Ctrl+F,

ENGINE - add name of DB

set TIME_ZONE to your time zone.

Database Setup if you want a DB other than SQLite

If you wish to use another database, install the appropriate database bindings, and change the following keys in the DATABASES 'default' item to match your database connection settings:

ENGINE – Either 'django.db.backends.sqlite3', 'django.db.backends.postgresql_psycopg2', 'django.db.backends.mysql', or 'django.db.backends.oracle'. Other backends are also available.

NAME – The name of your database. If you’re using SQLite, the database will be a file on your computer; in that case, NAME should be the full absolute path, including filename, of that file. The default value, os.path.join(BASE_DIR, 'db.sqlite3'), will

Page 27: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 27

store the file in your project directory.

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.sqlite3',

'NAME': DATABASE_PATH,

}

}

If you are not using SQLite as your database, additional settings such as USER, PASSWORD, HOST must be added.

Note

If you’re using PostgreSQL or MySQL, make sure you’ve created a database by this point.

Do that with “CREATE DATABASE database_name”; within your database’s interactive prompt.

If you’re using SQLite, you don’t need to create anything beforehand - the database file will

be created automatically when it is needed. Used in this example.

DATABASE_PATH = os.path.join(PROJECT_PATH, 'rango.db')

Here, we have defined the default database to use the SQLite Django backend. This provides us

with access to the lightweight python database, SQLite, which is great for development purposes.

Set is the NAME key/value pair, which we have set to DATABASE_PATH. For SQLite databases, the

remaining keys of USER, PASSWORD, HOST and PORT are not required and can thus be safely

removed.

python manage.py migrate creates DB

python manage.py runserver starts development server, lightweight web server written in Python, incl

in Django for rapid dev, no need to config Apache

no cursor until you stop server

Launch Django Server in PyCharm python manage.py startapp polls Actually creates app

If you choose sqlite3,

just verify auto user credentials, port and host

just launch the runserver task of the manage.py utility:

press Ctrl+Alt+R, and enter task name in the pop-up frame:

add an application to a project,

run the startapp task of the manage.py utility

Page 28: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 28

(Tools→Run manage.py task - startapp on the main menu).

in browser http://127.0.0.1:8000/

works

Each application you write in Django consists of a Python package

Diff Projects vs. apps

app is a Web application that does something – e.g., a Weblog system, a database of

public records or a simple poll app.

project is a collection of configuration and apps for a particular Web site. A project can

contain multiple apps. An app can be in multiple projects.

Performing administrative functions

First thing, create a superuser. To do that, type the superuser command in the manage.py console,

specify your email address, and password:

server not running

python manage.py createsuperuser

smooth

[email protected]

smooth

Page 29: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 29

smooth

Create Python model Change your models (in models.py).

Run python manage.py makemigrations to create migrations for those changes

Run python manage.py migrate to apply those changes to the database.

Use separate commands to make and apply migrations to make your development easier,

they’re also useable by other developers and in production.

Create the two initial data models for the Mysite application.

Django’s object relational mapping (ORM) functions

Django encapsulates databases tables through models.

Essentially, a model is a Python object that describes your data model/table.

Instead of directly working on the database table via SQL, all you have to do is manipulate

the corresponding Python object.

Edit polls/models.py

In mysite/models.py, we will define two classes -

both of which must inherit from django.db.models.Model.

The two Python classes will be the definitions for models representing Questions and

Choices.

Define the Question and Choice models fields as follows:

class Question(models.Model):

question_text = models.CharField(max_length=200)

pub_date = models.DateTimeField('date published')

def __unicode__(self):

return self.name

class Choice(models.Model):

question = models.ForeignKey(Question)

choice_text = models.CharField(max_length=200)

votes = models.IntegerField(default=0)

ForeignKey, a field type that allows us to create a one-to-many relationship.

Some of the most commonly used are listed below.

Page 30: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 30

CharField, a field for storing character data (e.g. strings). Specify max_length to

provide a maximum number of characters the field can store.

URLField, much like a CharField, but designed for storing resource URLs. You may

also specify a max_length parameter.

IntegerField, which stores integers.

DateField, which stores a Python datetime.date.

Synchronizing the Database

Our models are defined, Django needs to create table in our database SQLlite.

$ python manage.py syncdb

Synchronize the DB, converts the Django models into SQL tables.

$ python manage.py shell

run from within your Django project’s root directory

aid for debugging purposes

This will start an instance of the Python interpreter and load in your project’s settings for

you.

Configuring the Admin Interface Activate Model

web-based administrative interface that allows us to browse and edit data stored within our

models and corresponding database tables.

configure the admin interface

then access it.

mysite/settings.py

change the INSTALLED_APPS setting to include the 'polls'

INSTALLED_APPS = [

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'polls',

]

Now Django knows to include the polls app.

table django_admin_log is created

urls.py file.

URL pattern /admin/ points to the admin.site.urls module

Page 31: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 31

from django.conf.urls import patterns, include, url

from django.conf import settings

from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns('',

url(r'^rango/', include('rango.urls')),

url(r'^admin/', include(admin.site.urls)), # ADD THIS LINE

)

Django admin application needs to know which models we wish to make available to the admin interface.

admin.py

create a new python file in mysite application directory called admin.py.

Add

from django.contrib import admin

from mysite.models import Question, Choice

admin.site.register(Question)

admin.site.register(Choice)

This will register the models with the admin interface. I

start or restart the Django development server and visit:

Terminal

python manage.py runserver

smooth

smooth

http://127.0.0.1:8000/admin/.

Enter the superuser username and password (created when setting up database)

Following should be displayed

Page 32: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 32

The Django admin interface. Note the Mysite category, and the two models contained within.

python manage.py syncdb

python manage.py makemigrations polls

Django now sees changes or additions made

stored as a migration. To be physically migrated later

python manage.py sqlmigrate polls 0001

sqlmigrate doesn’t run the migration on your DB,

Only prints to the screen

Double check what Django will do.

The sqlmigrate command takes migration names and returns their SQL

Migrations for 'polls':

0001_initial.py:

- Create model Choice

- Create model Question

- Add field question to choice

output after command

BEGIN;

--

Page 33: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 33

-- Create model Choice

--

CREATE TABLE "polls_choice" (

"id" serial NOT NULL PRIMARY KEY,

"choice_text" varchar(200) NOT NULL,

"votes" integer NOT NULL

);

--

-- Create model Question

--

CREATE TABLE "polls_question" (

"id" serial NOT NULL PRIMARY KEY,

"question_text" varchar(200) NOT NULL,

"pub_date" timestamp with time zone NOT NULL

);

--

-- Add field question to choice

--

ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL;

ALTER TABLE "polls_choice" ALTER COLUMN "question_id" DROP DEFAULT;

CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id");

ALTER TABLE "polls_choice"

ADD CONSTRAINT "polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"

FOREIGN KEY ("question_id")

REFERENCES "polls_question" ("id")

DEFERRABLE INITIALLY DEFERRED;

COMMIT;

sqlmigrate

table names auto generated combining name of app- polls and lower case name of the

models - question and choice

primary keys auto gen

database field types auto set

python manage.py migrate

Actual migrate command,

Migrate any changes/tables created to DB

synchronizes the changes you made to your models with the schema in the database.

python manage.py check Check DB for errors

API

python manage.py shell

manage.py shell sets the DJANGO_SETTINGS_MODULE environment variable,

gives Django the Python import path to your mysite/settings.py file.

> from polls.models import Question, Choice

no information printed after entry

# Import the model classes we just wrote.

# No questions are in the system yet.

> Question.objects.all()

[]

# Create a new Question.

# Support for time zones is enabled in the default settings file, so

Page 34: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 34

# Django expects a datetime with tzinfo for pub_date. Use timezone.now()

# instead of datetime.datetime.now() and it will do the right thing.

> from django.utils import timezone

> q = Question(question_text="What's new?", pub_date=timezone.now())

> q.save()

# Save the object into the database. You have to call save() explicitly.

# Now it has an ID. Note that this might say "1L" instead of "1", depending

# on which database you're using. That's no biggie; it just means your

# database backend prefers to return integers as Python long integer

# objects.

> q.id

1

> q.question_text

# Access model field values via Python attributes.

"What's new?"

> q.pub_date

datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

> q.question_text = "What's up?"

# Change values by changing the attributes, then calling save().

> q.save()

> Question.objects.all()

[<Question: Question object>]

# objects.all() displays all the questions in the database.

Wait a minute. <Question: Question object> is, utterly, an unhelpful representation of

this object. Let’s fix that by editing the Question model (in the polls/models.py file)

and adding a __unicode__() method to both Question and Choice:

It’s important to add __unicode__() methods to your models, not only for your own

convenience when dealing with the interactive prompt, but also because objects’ representations are used throughout Django’s automatically generated admin.

polls/models.py

import datetime

from django.db import models

from django.utils import timezone

class Question(models.Model):

# ...

def was_published_recently(self):

return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

python manage.py shell

new Python interactive shell

Page 35: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 35

> from polls.models import Question, Choice

# Make sure our __str__() addition worked.

> Question.objects.all()

[<Question: What's up?>]

# Django provides a rich database lookup API that's entirely driven by

# keyword arguments.

> Question.objects.filter(id=1)

[<Question: What's up?>]

> Question.objects.filter(question_text__startswith='What')

[<Question: What's up?>]

> from django.utils import timezone # Get the question that was published this year

> current_year = timezone.now().year

> Question.objects.get(pub_date__year=current_year)

<Question: What's up?>

> Question.objects.get(id=2) # Request an ID that doesn't exist, this will raise an exception

Traceback (most recent call last):

...

DoesNotExist: Question matching query does not exist.

> Question.objects.get(pk=1)

<Question: What's up?>

# Lookup by a primary key is the most common case, so Django provides a

# shortcut for primary-key exact lookups.

# The following is identical to Question.objects.get(id=1).

> q = Question.objects.get(pk=1) # Make sure our custom method worked.

> q.was_published_recently()

True

> q = Question.objects.get(pk=1)

# Give the Question a couple of Choices. The create call constructs a new

# Choice object, does the INSERT statement, adds the choice to the set

# of available choices and returns the new Choice object. Django creates

# a set to hold the "other side" of a ForeignKey relation

# (e.g. a question's choice) which can be accessed via the API.

> q.choice_set.all() Display any choices from the related object set -- none so far.

[]

# Create three choices.

> q.choice_set.create(choice_text='Not much', votes=0)

<Choice: Not much>

> q.choice_set.create(choice_text='The sky', votes=0)

<Choice: The sky>

Page 36: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 36

> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

Choice objects have API access to their related Question objects.

> c.question

<Question: What's up?>

# And vice versa: Question objects get access to Choice objects.

> q.choice_set.all()

[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]

> q.choice_set.count()

# The API automatically follows relationships as far as you need.

# Use double underscores to separate relationships.

# This works as many levels deep as you want; there's no limit.

# Find all Choices for any question whose pub_date is in this year

# (reusing the 'current_year' variable we created above).

> Choice.objects.filter(question__pub_date__year=current_year)

[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]

# Let's delete one of the choices. Use delete() for that.

> c = q.choice_set.filter(choice_text__startswith='Just hacking')

> c.delete()

5. Customize Users

A. Creating an admin user

Django entirely automates creation of admin interfaces for models

python manage.py createsuperuser

already done

Tell the admin that Question objects have an admin interface.

open the polls/admin.py file, and edit it to look like this:

from django.contrib import admin

from .models import Question

admin.site.register(Question)

Forms automatically generated from the Question Model

B. Customize admin form

re-ordering the fields on the edit form.

Change admin.site.register(Question) line with:

open file polls/admin.py

from django.contrib import admin

Page 37: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 37

from .models import Question

class QuestionAdmin(admin.ModelAdmin):

fieldsets = [

(None, {'fields': ['question_text']}),

('Date information', {'fields': ['pub_date']}),

]

admin.site.register(Question, QuestionAdmin)

You’ll follow this pattern – create a model admin object, then pass it as the second

argument to admin.site.register() – any time you need to change the admin options

for an object.

This particular change above makes the “Publication date” come before the “Question” field:

collapse- long form need to hide fields. click (show) to see fields

class QuestionAdmin(admin.ModelAdmin):

fieldsets = [

(None, {'fields': ['question_text']}),

('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),

]

Adding related objects

Add choices to Question admin page

Register Choice with admin like Question was registered in polls/admin.py

from django.contrib import admin

from .models import Choice, Question

# ...

admin.site.register(Choice)

python manage.py runserver

now have choice and question in admin page

ForeignKey is represented in the admin as a <select> box.

“Add Another” link next to “Question.” Every object with a ForeignKey relationship to

another gets this for free. When you click “Add Another,” you’ll get a popup window with

the “Add question” form. If you add a question in that window and click “Save,” Django will

save the question to the database and dynamically add it as the selected choice on the “Add choice” form you’re looking at

Add several Choices directly instead of one at a time

admin.py

Remove register() call, add ChoiceInline

Page 38: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 38

admin.site.register(Question)

admin.site.register(Choice)

class ChoiceInline(admin.StackedInline):

model = Choice

extra = 3

class QuestionAdmin(admin.ModelAdmin):

fieldsets = [

(None, {'fields': ['question_text']}),

('Date information', {'fields': ['pub_date'], 'classes':

['collapse']}),

]

inlines = [ChoiceInline]

admin.site.register(Question, QuestionAdmin)

more compact form polls/admin.py

class ChoiceInline(admin.TabularInline):

display individual fields.

By default, Django displays the str() of each object. But sometimes it’d be more helpful if we

could display individual fields. To do that, use the list_display admin option, which is a tuple

of field names to display, as columns, on the change list page for the object:

To do that, use the list_display admin option, which is a tuple of field names to display, as columns, on the change list page for the object:

polls/admin.py

class QuestionAdmin(admin.ModelAdmin):

# ...

list_display = ('question_text', 'pub_date', 'was_published_recently')

filter sidebar to filter changes list in the pub_date field:

polls/admin.py

list_filter = [‘pub_date’]

search_fields = ['question_text']

search capability

6. Templates in project directory (one with manage.py) create templates directory

mysite/settings.py change ‘DIRS’:[], to ‘DIRS’:[ os.path.join(BASE_DIR, 'templates')],

create admin directory inside templates

copy template = admin/base_site.html into the new admin directory

Customize template = Override template, change web page title to S____ K___ edit file base_site.html

H:\My Documents\- Soft langs, WAP, websites, Frameworks\- Python,

Django\mysite\templates\admin\base_site.html

note: django.contrib.admin is an application

Customize admin index page

admin/index.html. (Do the same as with admin/base_site.html in the previous section

Page 39: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 39

– copy it from the default directory to your custom template directory.)

Edit the file, and you’ll see it uses a template variable called app_list. That variable contains every installed Django app. Instead of using that, you can hard-code links to object-specific admin pages in whatever way you think is best.

polls/views.py

change HttpResponse

map it to a URL using polls/urls.py

create polls/urls.py from django.conf.urls import url

from . import views

urlpatterns = [

url(r'^$', views.index, name='index'),

]

point the root URLConf to the polls.urls

create mysite/urls.py

from django.conf.urls import include, url

from django.contrib import admin

urlpatterns = [

url(r'^polls/', include('polls.urls')),

url(r'^admin/', include(admin.site.urls)),

]

Web site /polls/34

Django will load the mysite.urls

because it’s pointed to by the ROOT_URLCONF setting.

It finds the variable named urlpatterns and traverses the regular expressions in order.

They include() functions we are using simply reference other URLConf. Note that the regular expressions for the include() functions don’t have a $ (end-of-string match character) but rather a trailing slash. Whenever Django encounters include(), it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLConf for further processing.

The idea behind include() is to make it easy to plug-and-play URLs. Since polls are in their own URLConf (polls/urls.py), they can be placed under “/polls/”, or under “/fun_polls/”, or under “/content/polls/”, or any other path root, and the app will still work.

Here’s what happens if a user goes to “/polls/34/” in this system:

Django will find the match at '^polls/'

Then, Django will strip off the matching text ("polls/") and send the remaining text – "34/" –

to the ‘polls.urls’ URLConf for further processing which matches r'^(?P<question_id>[0-

9]+)/$' resulting in a call to the detail() view like so:

detail(request=<HttpRequest object>, question_id='34')

C. Django’s template system to separate the design from Python

use Django’s template system to separate the design from Python by creating a template that the view can use.

Page 40: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 40

First, create a directory called templates in your polls directory. Django will look for templates in there.

Your project’s TEMPLATES setting describes how Django will load and render templates. The default settings file configures a DjangoTemplates backend whose APP_DIRS option is set to True. By convention DjangoTemplates looks for a “templates” subdirectory in each of the INSTALLED_APPS. This is how Django knows to find the polls templates even though we didn’t modify the DIRS option,

reference http://django.readthedocs.org/en/latest/intro/tutorial03.html to create new folders, files, code to use new templates

Use the template system

Back to the detail() view for our poll application. Given the context variable question, here’s what the polls/detail.html template might look like:

polls/templates/polls/detail.html

<h1>{{ question.question_text }}</h1>

<ul>

{% for choice in question.choice_set.all %}

<li>{{ choice.choice_text }}</li>

{% endfor %}

</ul>

The template system uses dot-lookup syntax to access variable attributes. In the example of

{{ question.question_text }}, first Django does a dictionary lookup on the object question. Failing

that, it tries an attribute lookup – which works, in this case. If attribute lookup had failed, it

would’ve tried a list-index lookup.

Method-calling happens in the {% for %} loop: question.choice_set.all is interpreted as the

Python code question.choice_set.all(), which returns an iterable of Choice objects and is suitable

for use in the {% for %} tag.

D. How to return an HttpResponse object

A shortcut: render()

It’s a very common idiom to load a template, fill a context and return an HttpResponse object

with the result of the rendered template. Django provides a shortcut. Here’s the full index() view, rewritten:

Removing hardcoded URLs in templates

initial URL link in polls/index.html template:

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>

because previously defined the name argument in the url() functions in the polls.urls

module, you can remove a reliance on specific URL paths defined in your url configurations by

using the {% url %} template tag:

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

The way this works is by looking up the URL definition as specified in the polls.urls module. You can see exactly where the URL name of ‘detail’ is defined below:

...

# the 'name' value as called by the {% url %} template tag

url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),

...

If you want to change the URL of the polls detail view to something else, perhaps to something

like polls/specifics/12/ instead of doing it in the template (or templates) you would change

Page 41: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 41

it in polls/urls.py:

...

# added the word 'specifics'

url(r'^specifics/(?P<question_id>[0-9]+)/$', views.detail, name='detail'),

...

How to differentiate the URL names between Multiple applications in a Django project

answer add namespaces to the root URLConf in mysite/urls.py with {% url %} tag

E. Template updates

open

polls/templates/polls/detail.html

<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'polls:vote' question.id %}" method="post">

{% csrf_token %}

{% for choice in question.choice_set.all %}

<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{

choice.id }}" />

<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />

{% endfor %}

<input type="submit" value="Vote" />

</form>

A quick rundown:

The above template displays a radio button for each question choice. The value of each radio button is the associated question choice’s ID. The name of each radio button is "choice". That means, when somebody selects one of the radio buttons and submits the form, it’ll send the POST data choice=# where # is the ID of the selected choice. This is the basic concept of HTML forms.

We set the form’s action to {% url 'polls:vote' question.id %}, and we set method="post". Using method="post" (as opposed to method="get") is very important, because the act of submitting this form will alter data server-side. Whenever you create a form that alters data server-side, use method="post". This tip isn’t specific to Django; it’s just good Web development practice.

forloop.counter indicates how many times the for tag has gone through its loop

Since we’re creating a POST form (which can have the effect of modifying data), we need to worry about Cross Site Request Forgeries. Thankfully, you don’t have to worry too hard, because Django comes with a very easy-to-use system for protecting against it. In short, all POST forms that are targeted at internal URLs should use the {% csrf_token %} template tag.

Need to create a Django view that handles the submitted data and does something with it. Add

the following:

polls/views.py

from django.shortcuts import get_object_or_404, render

from django.http import HttpResponseRedirect, HttpResponse

from django.core.urlresolvers import reverse

from .models import Choice, Question

# ...

def vote(request, question_id):

p = get_object_or_404(Question, pk=question_id)

try:

selected_choice = p.choice_set.get(pk=request.POST['choice'])

except (KeyError, Choice.DoesNotExist):

Page 42: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 42

# Redisplay the question voting form.

return render(request, 'polls/detail.html', {

'question': p,

'error_message': "You didn't select a choice.",

})

else:

selected_choice.votes += 1

selected_choice.save()

# Always return an HttpResponseRedirect after successfully dealing

# with POST data. This prevents data from being posted twice if a

# user hits the Back button.

return HttpResponseRedirect(reverse('polls:results', args=(p.id,)))

request.POST is a dictionary-like object that lets you access submitted data by key name. In this case, request.POST['choice'] returns the ID of the selected choice, as a string. request.POST values are always strings.

Note that Django also provides request.GET for accessing GET data in the same way – but we’re explicitly using request.POST in our code, to ensure that data is only altered via a POST call.

request.POST['choice'] will raise KeyError if choice wasn’t provided in POST data. The above code checks for KeyError and redisplays the question form with an error message if choice isn’t given.

After incrementing the choice count, the code returns an HttpResponseRedirect rather than a normal HttpResponse. HttpResponseRedirect takes a single argument: the URL to which the user will be redirected (see the following point for how we construct the URL in this case).

As the Python comment above points out, you should always return an HttpResponseRedirect after successfully dealing with POST data. This tip isn’t specific to Django; it’s just good Web development practice.

We are using the reverse() function in the HttpResponseRedirect constructor in this example. This function helps avoid having to hardcode a URL in the view function. It is given the name of the view that we want to pass control to and the variable portion of the URL pattern that points to that view. In this case, using the URLConf we set up in Tutorial 3, this reverse() call will return a string like

'/polls/3/results/'

... where the 3 is the value of p.id. This redirected URL will then call the 'results' view to display the final page.

request is a HttpRequest object.

After somebody votes in a question, the vote() view redirects to the results page for the

question. Let’s write that view:

polls/views.py

from django.shortcuts import get_object_or_404, render

def results(request, question_id):

question = get_object_or_404(Question, pk=question_id)

return render(request, 'polls/results.html', {'question': question})

This is almost exactly the same as the detail() view from Tutorial 3. The only difference is the

Page 43: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 43

template name. We’ll fix this redundancy later.

Now, create a polls/results.html template:

polls/templates/polls/results.html

<h1>{{ question.question_text }}</h1>

<ul>

{% for choice in question.choice_set.all %}

<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{

choice.votes|pluralize }}</li>

{% endfor %}

</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>

Now, go to /polls/1/ in your browser and vote in the question. You should see a results page

that gets updated each time you vote. If you submit the form without having chosen a choice,

you should see the error message.

Page 44: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 44

7. Use generic views: Less code is better

These views represent a common case of basic Web development: getting data from the database according to a parameter passed in the URL, loading a template and returning the rendered template. Because this is so common, Django provides a shortcut, called the “generic views” system.

Generic views abstract common patterns to the point where you don’t even need to write Python code to write an app.

Let’s convert our poll app to use the generic views system, so we can delete a bunch of our own code. We’ll just have to take a few steps to make the conversion. We will:

Convert the URLConf.

Delete some of the old, unneeded views.

Introduce new views based on Django’s generic views.

Read on for details.

Why the code-shuffle?

Generally, when writing a Django app, you’ll evaluate whether generic views are a good fit for your problem, and you’ll use them from the beginning, rather than refactoring your code halfway through. But this tutorial intentionally has focused on writing the views “the hard way” until now, to focus on core concepts.

You should know basic math before you start using a calculator.

F. Amend URLConf

First, open the polls/urls.py URLConf and change it like so:

polls/urls.py from django.conf.urls import url

from . import views

urlpatterns = [

url(r'^$', views.IndexView.as_view(), name='index'),

url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),

url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),

url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),

]

Note that the name of the matched pattern in the regexes of the second and third

patterns has changed from <question_id> to <pk>.

Amend views

Next, we’re going to remove our old index, detail, and results views and use Django’s

generic views instead. To do so, open the polls/views.py file and change it like so:

polls/views.py from django.shortcuts import get_object_or_404, render

from django.http import HttpResponseRedirect

from django.core.urlresolvers import reverse

from django.views import generic

from .models import Choice, Question

class IndexView(generic.ListView):

template_name = 'polls/index.html'

context_object_name = 'latest_question_list'

def get_queryset(self):

Page 45: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 45

"""Return the last five published questions."""

return Question.objects.order_by('-pub_date')[:5]

class DetailView(generic.DetailView):

model = Question

template_name = 'polls/detail.html'

class ResultsView(generic.DetailView):

model = Question

template_name = 'polls/results.html'

def vote(request, question_id):

... # same as above

We’re using two generic views here: ListView and DetailView. Respectively, those two views

abstract the concepts of “display a list of objects” and “display a detail page for a particular type

of object.”

Each generic view needs to know what model it will be acting upon. This is provided using the

model attribute.

The DetailView generic view expects the primary key value captured from the URL to be called

"pk", so we’ve changed question_id to pk for the generic views.

By default, the DetailView generic view uses a template called <app name>/<model

name>_detail.html. In our case, it would use the template "polls/question_detail.html".

The template_name attribute is used to tell Django to use a specific template name instead of

the autogenerated default template name. We also specify the template_name for the results

list view – this ensures that the results view and the detail view have a different appearance when

rendered, even though they’re both a DetailView behind the scenes.

Similarly, the ListView generic view uses a default template called <app name>/<model

name>_list.html; we use template_name to tell ListView to use our existing

"polls/index.html" template.

In previous parts of the tutorial, the templates have been provided with a context that contains

the question and latest_question_list context variables. For DetailView the question variable is

provided automatically – since we’re using a Django model (Question), Django is able to

determine an appropriate name for the context variable. However, for ListView, the

automatically generated context variable is question_list. To override this we provide the

context_object_name attribute, specifying that we want to use latest_question_list instead. As an

alternative approach, you could change your templates to match the new default context variables – but it’s a lot easier to just tell Django to use the variable you want.

Run the server, and use your new polling app based on generic views.

Page 46: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 46

Standalone installers

Use pip to install Pyinstaller

PyCharm

Terminal

python --version

= 3.4.3

pip --version

= pip 7.1.2 from

C:\Program Files\Python

type pip install pyinstaller

H:\My Documents\Soft\Python\MysiteProject>pip install pyinstaller

You are using pip version 6.1.1, however version 7.1.2 is available.

You should consider upgrading via the 'pip install --upgrade pip' command.

Collecting pyinstaller

Downloading PyInstaller-2.1.tar.gz (4.8MB)

100% |################################| 4.8MB 70kB/s eta 0:00:011

Complete output from command python setup.py egg_info:

Traceback (most recent call last):

File "<string>", line 20, in <module>

File "C:\Users\owner\AppData\Local\Temp\pip-build-qmyqrcnm\pyinstaller\set

from PyInstaller import get_version

File "C:\Users\owner\AppData\Local\Temp\pip-build-qmyqrcnm\pyinstaller\PyI

from PyInstaller import compat

----------------------------------------

Command "python setup.py egg_info" failed with error code 1 in C:\Users

Start PyCharm run as Administrator

Terminal

Microsoft Windows [Version 6.1.7601]

Copyright (c) 2009 Microsoft Corporation. All rights reserved.

H:\My Documents\Soft\Python\MysiteProject>pip install --upgrade pip

Requirement already up-to-date: pip in c:\program files\python\lib\site-packages

H:\My Documents\Soft\Python\MysiteProject>

H:\My Documents\Soft\Python\MysiteProject>pip install pyinstaller

Collecting pyinstaller

Using cached PyInstaller-2.1.tar.gz

Complete output from command python setup.py egg_info:

Traceback (most recent call last):

File "<string>", line 20, in <module>

File "C:\Users\owner\AppData\Local\Temp\pip-build-

z2ojb2f4\pyinstaller\setup.py", line 18, in <module>

from PyInstaller import get_version

File "C:\Users\owner\AppData\Local\Temp\pip-build-

z2ojb2f4\pyinstaller\PyInstaller\__init__.py", line 32, in <module>

from PyInstaller import compat

File "C:\Users\owner\AppData\Local\Temp\pip-build-

z2ojb2f4\pyinstaller\PyInstaller\compat.py", line 129

if sys.maxint > 2L ** 32:

^

SyntaxError: invalid syntax

----------------------------------------

Command "python setup.py egg_info" failed with error code 1 in

C:\Users\owner\AppData\Local\Temp\pip-build-z2ojb2f4\pyinstaller

Page 47: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 47

pyinstaller incompatible with python 3 so use newest

use pyinstaller python3 branch on github

pip3 install https://github.com/pyinstaller/pyinstaller/archive/python3.zip

H:\My Documents\Soft\Python\MysiteProject>pip3 install

https://github.com/pyinstaller/pyinstaller/archive/python3.zip

Collecting https://github.com/pyinstaller/pyinstaller/archive/python3.zip

Downloading https://github.com/pyinstaller/pyinstaller/archive/python3.zip

\ 3.1MB 682kB/ss

Requirement already satisfied (use --upgrade to upgrade): setuptools in c:\program

files\python\lib\site-packages\setuptools-18.3.1-py3.4.egg (from

PyInstaller==3.0.dev1)

Collecting pypiwin32 (from PyInstaller==3.0.dev1)

Downloading pypiwin32-219-cp34-none-win_amd64.whl (8.6MB)

100% |################################| 8.6MB 43kB/s eta 0:00:01

Installing collected packages: pypiwin32, PyInstaller

Running setup.py install for PyInstaller

Successfully installed PyInstaller-3.0.dev1 pypiwin32-219

H:\My Documents\Soft\Python\MysiteProject>

PyInstaller - Successfully installed PyInstaller-3.0.dev1 pypiwin32-219

pip is the preferred installer program. Starting with Python 2.7.9, it is included by default with the Python binary installers.

distutils is the original build and distribution system first added to the Python standard library in 1998. While direct use of distutils is being phased out, it still laid the foundation for the current packaging and distribution infrastructure, and it not only remains part of the standard library, but its name lives on in other ways (such as the name of the mailing list used to coordinate Python packaging standards development).

Create a simple app.py file, prints hello world

Python Console, working commands

Pycharm run command, green triangle or run menu option

output to Python Console

from app.py import *

ran perfect 1st time in Python Console, doesn’t work if tried again

highlight code, rt click, run selection

ran perfect in Python Console

Python Console, not commands working

Page 48: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 48

noticed pyCharm 4.5.4\helpers\pydev\pydevconsole.py

PyDev Console: starting

64 bit AMD64 on win32

Pyinstaller installed

pyinstaller.exe --onefile --windowed app.py

1. Distutils

A. An Introduction ¶

https://docs.python.org/3.5/distutils/introduction.html#concepts-terminology

ex. distribute a module ( source distribution , not executable) for this module, you would called

foo, contained in a file called foo.py then write your setup script thus:

create a setup script, setup.py,

from distutils.core import setup

setup(name='foo',

version='1.0',

py_modules=['foo'],

)

Windows, open a command prompt window (Start ‣ Accessories) and enter:

setup.py sdist

Or, from the PyCharm Terminal :

python setup.py sdist

sdist will create an archive file (e.g., tarball on Unix, ZIP file on Windows) containing your setup

script setup.py, and your module foo.py. The archive file will be named foo-1.0.tar.gz (or .zip), and will unpack into a directory foo-1.0.

If an end-user wishes to install your foo module, all she has to do is download foo-1.0.tar.gz (or

.zip), unpack it, and—from the foo-1.0 directory—run

python setup.py install

which will ultimately copy foo.py to the appropriate directory for third-party modules in their

Python installation.

B. Concepts & Terminology

Using the Distutils is quite simple, both for module developers and for users/administrators

installing third-party modules. As a developer, your responsibilities (apart from writing solid,

well-documented and well-tested code, of course!) are:

Page 49: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 49

write a setup script (setup.py by convention)

(optional) write a setup configuration file

create a source distribution

(optional) create one or more built (binary) distributions

C. A Simple Example

If all you want to do is distribute a module called foo, contained in a file foo.py, then your

setup script can be as simple as this:

from distutils.core import setup

setup(name='foo',

version='1.0',

py_modules=['foo'],

)

those keyword arguments fall into two categories: package metadata (name, version number) and information about what’s in the package (a list of pure Python modules, in this case)

modules are specified by module name, not filename (the same will hold true for packages and extensions)

To create a source distribution for this module, you would create a setup script, setup.py, containing the above code, and run this command from a terminal:

python setup.py sdist

For Windows, open a command prompt window (Start ‣ Accessories) and change the command

to:

setup.py sdist

sdist will create an archive file (e.g., tarball on Unix, ZIP file on Windows) containing your

setup script setup.py, and your module foo.py. The archive file will be named foo-

1.0.tar.gz (or .zip), and will unpack into a directory foo-1.0.

If an end-user wishes to install your foo module, all she has to do is download foo-1.0.tar.gz

(or .zip), unpack it, and—from the foo-1.0 directory—run

python setup.py install

which will ultimately copy foo.py to the appropriate directory for third-party modules in their Python installation.

This simple example demonstrates some fundamental concepts of the Distutils. First, both

developers and installers have the same basic user interface, i.e. the setup script. The difference

is which Distutils commands they use: the sdist command is almost exclusively for module

developers, while install is more often for installers (although most developers will want to

install their own code occasionally).

If you want to make things really easy for your users, you can create one or more built

distributions for them. For instance, if you are running on a Windows machine, and want to make

things easy for other Windows users, you can create an executable installer (the most appropriate

type of built distribution for this platform) with the bdist_wininst command. For example:

python setup.py bdist_wininst

Page 50: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 50

will create an executable installer, foo-1.0.win32.exe, in the current directory.

Other useful built distribution formats are RPM, implemented by the bdist_rpm command,

Solaris pkgtool (bdist_pkgtool), and HP-UX swinstall (bdist_sdux). For example, the

following command will create an RPM file called foo-1.0.noarch.rpm:

python setup.py bdist_rpm

(The bdist_rpm command uses the rpm executable, therefore this has to be run on an RPM-

based system such as Red Hat Linux, SuSE Linux, or Mandrake Linux.)

You can find out what distribution formats are available at any time by running

python setup.py bdist --help-formats

D. General Python terminology

If you’re reading this document, you probably have a good idea of what modules, extensions,

and so forth are. Nevertheless, just to be sure that everyone is operating from a common starting point, we offer the following glossary of common Python terms:

1. module

the basic unit of code reusability in Python: a block of code imported by some other code.

Three types of modules concern us here: pure Python modules, extension modules, and

packages.

2. pure Python module

a module written in Python and contained in a single .py file (and possibly associated .pyc

files). Sometimes referred to as a “pure module.”

3. extension module

a module written in the low-level language of the Python implementation: C/C++ for Python,

Java for Jython. Typically contained in a single dynamically loadable pre-compiled file, e.g. a

shared object (.so) file for Python extensions on Unix, a DLL (given the .pyd extension) for

Python extensions on Windows, or a Java class file for Jython extensions. (Note that

currently, the Distutils only handles C/C++ extensions for Python.)

4. package

a module that contains other modules; typically contained in a directory in the filesystem and

distinguished from other directories by the presence of a file __init__.py.

5. root package

the root of the hierarchy of packages. (This isn’t really a package, since it doesn’t have an

__init__.py file. But we have to call it something.) The vast majority of the standard

library is in the root package, as are many small, standalone third-party modules that don’t

belong to a larger module collection. Unlike regular packages, modules in the root package

can be found in many directories: in fact, every directory listed in sys.path contributes modules to the root package.

E. Distutils-specific terminology

The following terms apply more specifically to the domain of distributing Python modules using

the Distutils:

1. module distribution

a collection of Python modules distributed together as a single downloadable resource and

Page 51: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 51

meant to be installed en masse. Examples of some well-known module distributions are

NumPy, SciPy, PIL (the Python Imaging Library), or mxBase. (This would be called a

package, except that term is already taken in the Python context: a single module distribution may contain zero, one, or many Python packages.)

2. pure module distribution

a module distribution that contains only pure Python modules and packages. Sometimes

referred to as a “pure distribution.”

3. non-pure module distribution

a module distribution that contains at least one extension module. Sometimes referred to as a

“non-pure distribution.”

4. distribution root

the top-level directory of your source tree (or source distribution); the directory where

setup.py exists. Generally setup.py will be run from this directory.

2. Create Built Distributions

Python organization recommends https://docs.python.org/3.5/distutils/builtdist.html

“built distribution” is the term used because

not “binary package” because not necessarily binary, it might contain only Python source or byte code.

not package, because that word is already spoken for in Python.

not “installer” is a term specific to the world of mainstream desktop systems.

therefore use build distribution

RPM-based Linux systems, it’s a binary RPM;

Windows users, it’s an executable installer;

Debian-based Linux users, it’s a Debian package;

and so forth.

Distutils are designed to enable module developers to concentrate on their specialty—writing

code and creating source distributions—while an intermediary species called packagers springs

up to turn source distributions into built distributions for as many platforms as there are packagers.

a packager uses the setup script and the bdist command family to generate built distributions.

As a simple example, if I run the following command in the Distutils source tree:

python setup.py bdist

then the Distutils builds my module distribution (the Distutils itself in this case), does a “fake”

installation (also in the build directory), and creates the default type of built distribution for my

platform. The default format for built distributions is a tar file on Unix, and a simple executable

installer on Windows.

Thus, the above command on a Unix system creates Distutils-1.0.plat.tar.gz; unpacking

this tarball from the right place installs the Distutils just as though you had downloaded the

source distribution and run python setup.py install. (The “right place” is either the root of

the filesystem or Python’s prefix directory, depending on the options given to the bdist_dumb

command; the default is to make dumb distributions relative to prefix.)

Obviously, for pure Python distributions, this isn’t any simpler than just running python

setup.py install—but for non-pure distributions, which include extensions that would need

to be compiled, it can mean the difference between someone being able to use your extensions or

Page 52: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 52

not. And creating “smart” built distributions, such as an RPM package or an executable installer

for Windows, is far more convenient for users even if your distribution doesn’t include any

extensions.

The bdist command has a --formats option, similar to the sdist command, which you can use to

select the types of built distribution to generate: for example,

Page 53: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 53

python setup.py bdist --format=zip

would, when run on a Unix system, create Distutils-1.0.plat.zip—again, this archive

would be unpacked from the root directory to install the Distutils.

The available formats for built distributions are:

Format Description Notes

gztar gzipped tar file (.tar.gz) (1)

bztar bzipped tar file (.tar.bz2)

xztar xzipped tar file (.tar.xz)

ztar compressed tar file (.tar.Z) (3)

tar tar file (.tar)

zip zip file (.zip) (2),(4)

rpm RPM (5)

pkgtool Solaris pkgtool

sdux HP-UX swinstall

wininst self-extracting ZIP file for Windows (4)

msi Microsoft Installer.

Changed in version 3.5: Added support for the xztar format.

Notes:

1. default on Unix

2. default on Windows

3. requires external compress utility.

4. requires either external zip utility or zipfile module (part of the standard Python library since

Python 1.6)

5. requires external rpm utility, version 3.0.4 or better (use rpm --version to find out which version

you have)

You don’t have to use the bdist command with the --formats option; you can also use the

command that directly implements the format you’re interested in. Some of these bdist “sub-

commands” actually generate several similar formats; for instance, the bdist_dumb

command generates all the “dumb” archive formats (tar, gztar, bztar, xztar, ztar, and

zip), and bdist_rpm generates both binary and source RPMs. The bdist sub-commands, and

the formats generated by each, are:

Command Formats

bdist_dumb tar, gztar, bztar, xztar, ztar, zip

bdist_rpm rpm, srpm

bdist_wininst wininst

bdist_msi msi

The following sections give details on the individual bdist_* commands.

5. Creating RPM packages

The RPM format is used by many popular Linux distributions, including Red Hat, SuSE, and

Mandrake. If one of these (or any of the other RPM-based Linux distributions) is your usual

environment, creating RPM packages for other users of that same distribution is trivial.

Depending on the complexity of your module distribution and differences between Linux

Page 54: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 54

distributions, you may also be able to create RPMs that work on different RPM-based distributions.

The usual way to create an RPM of your module distribution is to run the bdist_rpm

command:

python setup.py bdist_rpm

or the bdist command with the --format option:

python setup.py bdist --formats=rpm

The former allows you to specify RPM-specific options; the latter allows you to easily

specify multiple formats in one run. If you need to do both, you can explicitly specify

multiple bdist_* commands and their options:

python setup.py bdist_rpm --packager="John Doe <[email protected]>" \

bdist_wininst --target-version="2.0"

Creating RPM packages is driven by a .spec file, much as using the Distutils is driven by the

setup script. To make your life easier, the bdist_rpm command normally creates a .spec file

based on the information you supply in the setup script, on the command line, and in any

Distutils configuration files. Various options and sections in the .spec file are derived from options in the setup script as follows:

Additionally, there are many options in .spec files that don’t have corresponding options in

the setup script. Most of these are handled through options to the bdist_rpm command as follows:

RPM .spec file

option or section bdist_rpm option default value

Release release “1”

Group group “Development/Libraries”

Vendor vendor (see above)

Packager packager (none)

Provides provides (none)

Requires requires (none)

Conflicts conflicts (none)

RPM .spec file option or

section Distutils setup script option

Name name

Summary (in preamble) description

Version version

Vendor author and author_email, or — & maintainer

and maintainer_email

Copyright license

Url url

%description (section) long_description

Page 55: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 55

RPM .spec file

option or section bdist_rpm option default value

Obsoletes obsoletes (none)

Distribution distribution_name (none)

BuildRequires build_requires (none)

Icon icon (none)

Obviously, supplying even a few of these options on the command-line would be tedious and

error-prone, so it’s usually best to put them in the setup configuration file, setup.cfg—see

section Writing the Setup Configuration File. If you distribute or package many Python

module distributions, you might want to put options that apply to all of them in your personal

Distutils configuration file (~/.pydistutils.cfg). If you want to temporarily disable this

file, you can pass the --no-user-cfg option to setup.py.

There are three steps to building a binary RPM package, all of which are handled automatically by the Distutils:

6. create a .spec file, which describes the package (analogous to the Distutils setup script; in fact,

much of the information in the setup script winds up in the .spec file)

7. create the source RPM

8. create the “binary” RPM (which may or may not contain binary code, depending on whether your

module distribution contains Python extensions)

Normally, RPM bundles the last two steps together; when you use the Distutils, all three

steps are typically bundled together.

If you wish, you can separate these three steps. You can use the --spec-only option to make

bdist_rpm just create the .spec file and exit; in this case, the .spec file will be written to

the “distribution directory”—normally dist/, but customizable with the --dist-dir option.

(Normally, the .spec file winds up deep in the “build tree,” in a temporary directory created by bdist_rpm.)

6. Creating Windows Installers

Executable installers are the natural format for binary distributions on Windows. They

display a nice graphical user interface, display some information about the module

distribution to be installed taken from the metadata in the setup script, let the user select a few options, and start or cancel the installation.

Since the metadata is taken from the setup script, creating Windows installers is usually as

easy as running:

python setup.py bdist_wininst

or the bdist command with the --formats option:

python setup.py bdist --formats=wininst

If you have a pure module distribution (only containing pure Python modules and packages),

the resulting installer will be version independent and have a name like foo-1.0.win32.exe. These installers can even be created on Unix platforms or Mac OS X.

If you have a non-pure distribution, the extensions can only be created on a Windows

platform, and will be Python version dependent. The installer filename will reflect this and

now has the form foo-1.0.win32-py2.0.exe. You have to create a separate installer for every Python version you want to support.

The installer will try to compile pure modules into bytecode after installation on the target

system in normal and optimizing mode. If you don’t want this to happen for some reason,

Page 56: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 56

you can run the bdist_wininst command with the --no-target-compile and/or the --no-target-optimize option.

By default the installer will display the cool “Python Powered” logo when it is run, but you

can also supply your own 152x261 bitmap which must be a Windows .bmp file with the --bitmap option.

The installer will also display a large title on the desktop background window when it is run,

which is constructed from the name of your distribution and the version number. This can be changed to another text by using the --title option.

The installer file will be written to the “distribution directory” — normally dist/, but customizable with the --dist-dir option.

7. Cross-compiling on Windows

Starting with Python 2.6, distutils is capable of cross-compiling between Windows platforms.

In practice, this means that with the correct tools installed, you can use a 32bit version of

Windows to create 64bit extensions and vice-versa.

To build for an alternate platform, specify the --plat-name option to the build command.

Valid values are currently ‘win32’, ‘win-amd64’ and ‘win-ia64’. For example, on a 32bit

version of Windows, you could execute:

python setup.py build --plat-name=win-amd64

to build a 64bit version of your extension. The Windows Installers also support this option, so the command:

python setup.py build --plat-name=win-amd64 bdist_wininst

would create a 64bit installation executable on your 32bit version of Windows.

To cross-compile, you must download the Python source code and cross-compile Python

itself for the platform you are targeting - it is not possible from a binary installation of

Python (as the .lib etc file for other platforms are not included.) In practice, this means the

user of a 32 bit operating system will need to use Visual Studio 2008 to open the

PCBuild/PCbuild.sln solution in the Python source tree and build the “x64” configuration of the ‘pythoncore’ project before cross-compiling extensions is possible.

Note that by default, Visual Studio 2008 does not install 64bit compilers or tools. You may

need to reexecute the Visual Studio setup process and select these tools (using Control Panel-

>[Add/Remove] Programs is a convenient way to check or modify your existing install.)

8. The Postinstallation script

Starting with Python 2.3, a postinstallation script can be specified with the --install-script

option. The basename of the script must be specified, and the script filename must also be

listed in the scripts argument to the setup function.

This script will be run at installation time on the target system after all the files have been

copied, with argv[1] set to -install, and again at uninstallation time before the files are

removed with argv[1] set to -remove.

The installation script runs embedded in the windows installer, every output (sys.stdout,

sys.stderr) is redirected into a buffer and will be displayed in the GUI after the script has

finished.

Some functions especially useful in this context are available as additional built-in functions

in the installation script.

directory_created(path)

Page 57: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 57

file_created(path)

These functions should be called when a directory or file is created by the postinstall script at

installation time. It will register path with the uninstaller, so that it will be removed when the

distribution is uninstalled. To be safe, directories are only removed if they are empty.

get_special_folder_path(csidl_string)

This function can be used to retrieve special folder locations on Windows like the Start Menu

or the Desktop. It returns the full path to the folder. csidl_string must be one of the following

strings:

"CSIDL_APPDATA"

"CSIDL_COMMON_STARTMENU"

"CSIDL_STARTMENU"

"CSIDL_COMMON_DESKTOPDIRECTORY"

"CSIDL_DESKTOPDIRECTORY"

"CSIDL_COMMON_STARTUP"

"CSIDL_STARTUP"

"CSIDL_COMMON_PROGRAMS"

"CSIDL_PROGRAMS"

"CSIDL_FONTS"

If the folder cannot be retrieved, OSError is raised.

Which folders are available depends on the exact Windows version, and probably also the

configuration. For details refer to Microsoft’s documentation of the

SHGetSpecialFolderPath() function.

create_shortcut(target, description, filename[, arguments[, workdir[,

iconpath[, iconindex]]]])

This function creates a shortcut. target is the path to the program to be started by the shortcut.

description is the description of the shortcut. filename is the title of the shortcut that the user

will see. arguments specifies the command line arguments, if any. workdir is the working

directory for the program. iconpath is the file containing the icon for the shortcut, and

iconindex is the index of the icon in the file iconpath. Again, for details consult the Microsoft

documentation for the IShellLink interface.

Major problem upgrading to Python 3.5.0a2

python.exe - Entry Point Not Found

“The procedure entry point ucrtbase.abort could not be located in the dynamic link library

api-ms-crt-runtime-l1-1-0.dll

few others with same error, not all python. problem in ucrtbase.abort is the problem

uninstall 3.5, restart, reinstall 3.5 (owner/appdata), restart, error

uninstall 3.5, restart, reinstall all users (program files), restart, error

Page 58: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 58

uninstall Visual C++ redist, restart, install, restart, error

download .dll, backedup existing copy, copied new .dll to windows/system32 dir, restart,

install 3.4.3, restart, WORKS Great 6 hr job!!!!!!!!

3. Setup after software delivery to client

Python 3.4.3

upgraded to 3.5.0a2 reference problems above, reinstalled 3.4

C:\Python34\ 9/14/15

from Pycharm C:\Users\owner\.PyCharm40 (5/12/15 )

to JetBrains PyCharm Community Edition 4.5.4 C:\Program Files

(x86)\JetBrains\PyCharm Community Edition 4.5.4\bin\pycharm.exe"

C:\Users\owner\PycharmProjects 9/13/15

Updated Environment Variables for Python

4. Vista User Access Control (UAC)

Starting with Python 2.6, bdist_wininst supports a --user-access-control option. The default is

‘none’ (meaning no UAC handling is done), and other valid values are ‘auto’ (meaning prompt

for UAC elevation if Python was installed for all users) and ‘force’ (meaning always prompt for

elevation).

5. WinPython and Inno Setup as a single-file .exe installer.

No dependencies, no prerequisites

installs a full standalone, isolated Python distribution, into C:\Program Files\MyApp\ like a regular program.

The end-user does not even need to know that the software is written in Python

This solution can be summarized in two words: WinPython and Inno Setup.

WinPython is a free scientific Python distribution for Windows that is portable, meaning that it is

completely isolated from the rest of the system. WinPython can be installed in a folder, which

can be moved anywhere, even on an USB stick, remaining entirely functional. WinPython is

bundled with a lot of existing Python packages, but the huge advantage is that it includes

graphical and command-line utilities to install/uninstall any Python package easily (from a zip or Windows binary installer generated by distutils).

Inno Setup is a free software for creating Windows installers. Building an installer requires to

write a plain text script that contains the instructions about what to install and where. It has a lot

of features, including desktop and start menu shortcuts, post-install scripts, etc. A wizard allows one to get started quickly and easily.

Page 59: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 59

Here is a summary of what you need to do to create an installer for your Python application.

First, create a folder with a WinPython distribution including all your Python dependencies, and

your own Python package as well. Second, create an installer that will just copy this folder

somewhere on the end-user hard drive, along with shortcuts to run your application. Then, you

can customize the installation process as you wish.

Step 1: customize your WinPython distribution

Create a folder named MyApplication somewhere on your development machine. This

folder will be copied to C:\Program Files\MyApplication by the installer.

Download and install WinPython into, say, MyApplication\WinPython-64bit-

2.7.5.0.

WinPython contains a GUI that lets you install/uninstall Python packages. There are a lot

of packages built in, but you can remove those that you don't need for your application.

You can also add new Python packages by dragging zip or exe installers (created with

distutils) into the GUI.

Step 2: create the installer

Install Inno Setup.

Use the wizard to create a new installer file (it is just a .iss text file).

Tell the wizard to copy your folder MyApplication to C:\Program

Files\MyApplication. The ISS code for this looks like this: [Files]

Source: "D:\Dev\MyApplication"; DestDir: "{app}"; Flags: ignoreversion

recursesubdirs createallsubdirs

Note the {app} variable which contains the user application path. See the list of Inno

Setup constants here.

Step 3: create the shortcuts

Create some shortcuts. Here is the ISS code to create a shorcut in the Start menu

launching a Python GUI application: [Icons]

Name: "{group}\Application"; Filename: "{app}\WinPython-64bit-

2.7.5.0\python-2.7.5.amd64\pythonw.exe"; WorkingDir: "{app}"; Parameters:

"""{app}\WinPython-64bit-2.7.5.0\python-2.7.5.amd64\Lib\site-

packages\myapplication\scripts\runmyapp.py"""; IconFilename:

"{app}\favicon.ico"

This code snippet assumes that the Python script running your application is in

myapplication\scripts\runmyapp.py. You could also have this script somewhere directly

in your application folder and not necessarily in your Python package. You can also specify

an icon as a .ico file.

You can create shortcuts on the desktop too. See more details here.

Step 4: customize the installation process

Inno Setup allows you to customize the installation process as you wish. Together with

Python scripts, you can really achieve anything. For instance, here is how you can run a

Python script at the end of the installation process.

[Run]

Filename: "{app}\WinPython-64bit-2.7.5.0\python-2.7.5.amd64\python.exe";

WorkingDir: "{app}"; Parameters: """{app}\postinstall.py"""; Flags:

runhidden

Here are a few directives that you can use to customize some aspects of the installation

wizard (icon, images, colors...):

Page 60: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 60

[Setup]

SetupIconFile=D:\Dev\myapp\favicon.ico

WizardImageFile=wizard.bmp

WizardImageStretch=no

WizardSmallImageFile=wizard-small.bmp

WizardImageBackColor=$ffffff

Python code to install packages

You can create Python scripts that the user runs by clicking on an icon (see the [Icons]

section above). You can for instance create a small utility that updates automatically your

application by checking the last installer version on a server, and downloading and executing

it automatically. Here is some Python code snippet that installs or updates a Python package in the user's WinPython distribution, from a zip or a Windows package created with distutils.

import sys

from winpython import wppm, utils

try:

dist = wppm.Distribution(sys.prefix)

package = wppm.Package(pathtoexefile)

dist.install(package)

except:

raise Exception("Unable to install the package.")

Conclusion

This solution may not be adapted to everyone. But I think it is best for regular Windows users

who are used to do everything with the mouse and who are scared by command line

interfaces. It allows any Python developer to create and distribute a graphical application as

easily as for a more standard C++ program. I imagine that games for Windows could be

written with Python and be easily distributed like this. Kivy, a Python library used in media applications and games, uses a similar technique as far as I know.

Finally, do take the time to browse Inno Setup's documentation. It is clear and well

organized. And take a look to WinPython, it is nice and powerful, even if the documentation could be better. Actually I may start using it as my day-to-day Python distribution.

WinPython - it's moved to SourceForge

F. Create a package for Windows

http://kivy.org/docs/guide/packaging-windows.html

Packaging your application for the Windows platform can only be done inside the Windows OS.

The following process has been tested on Windows 7 and the portable package of Kivy.

The package will be either 32 or 64 bits depending on which version of Python you ran it with.

NOTE: Currently, packages for Windows can be generated with Python 2.7 and Python 3.3+. However, Python 3.3+ support is still experimental

1. Requirements¶

Latest Kivy (the whole portable package, not only the github sourcecode)

PyInstaller 2.1 (pip install pyinstaller) for Python 2.7, and experimental PyInstaller 3.0

(pip install https://github.com/pyinstaller/pyinstaller/archive/python3.zip) for Python

3.3+.

2. Create the spec file¶

Note The following instructions is written for python 2.7, for other versions of python one

Page 61: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 61

should replace all instances of 2.7 or 27 with the appropriate version.

For this example, we’ll package the touchtracer example and embed a custom icon. The

touchtracer example is the kivy27\examples\demo\touchtracer directory and the main file is

named main.py.

1. Double click on the Kivy-2.7.bat and a console will open.

2. Create a folder into which the packaged app will be created and create the initial spec. For example

create a TouchApp directory in the same directory as Kivy-2.7.bat and do:

3. cd TouchApp

4. pyinstaller --name touchtracer ..\kivy27\examples\demo\touchtracer\main.py

5. You can also add an icon.ico file to the application folder in order to create an icon for the executable.

If you don’t have a .ico file available, you can convert your icon.png file to ico using the web app

ConvertICO. Save the icon.ico in the touchtracer directory and type:

6. pyinstaller --name touchtracer --

icon ..\kivy27\examples\demo\touchtracer\icon.ico ..\kivy27\examples\demo\touchtracer\main.py

7. For more options, please consult the PyInstaller 2.1 Manual.

8. The spec file will be touchtracer.spec located in TouchApp. Now we need to edit the spec file to add

kivy hooks to correctly build the exe. Open the spec file with your favorite editor and add theses lines

at the beginning of the spec:

9. from kivy.tools.packaging.pyinstaller_hooks import install_hooks

10. import os

11. install_hooks(globals())

In the Analysis() function, remove the hookspath=None parameter. If you don’t do this, the kivy package hook will not be used at all.

Then you need to change the COLLECT() call to add the data for touchtracer (touchtracer.kv,

particle.png, ...). Change the line to add a Tree() object. This Tree will search and add every file found in the touchtracer directory to your final package:

coll = COLLECT( exe, Tree('../kivy27/examples/demo/touchtracer/'),

a.binaries,

#...

)

If SDL2 is used the SDL2 dlls also needs to be included; so add the

following Tree object to collect:

Tree([f for f in os.environ.get('KIVY_SDL2_PATH', '').split(';') if 'bin'

in f][0])

Note Until 1.9.0, the windows distribution used PyGame for the core providers. From 1.9.0

and on, the windows distribution uses SDL2 instead and does not come with a PyGame

installation. If you’re using the 1.8.0 package with 1.9.0 or later code, or if you’re using the

1.9.0 or later package, but downloaded and need PyGame in your packaging app, you’ll have

to add the following code to your spec file due to kivy issue #1638. After the imports add the

following:

def getResource(identifier, *args, **kwargs):

if identifier == 'pygame_icon.tiff':

raise IOError()

return _original_getResource(identifier, *args, **kwargs)

import pygame.pkgdata

_original_getResource = pygame.pkgdata.getResource

Page 62: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 62

pygame.pkgdata.getResource = getResource

12. We are done. Your spec is ready to be executed!

3. Build the spec¶

1. Double click on Kivy-2.7.bat

2. Go to the TouchApp directory, and build the spec:

3. cd TouchApp

4. pyinstaller touchtracer.spec

5. The package will be in the TouchApp\dist\touchtracer directory.

4. Including Gstreamer¶

If you wish to use Gstreamer, you’ll need to further modify the spec file.

1. Kivy does some magic when trying to find which version of gstreamer and its bindings are available.

In order for pyinstaller to find the correct gstreamer modules, you have to import core.video in the

spec file before doing anything:

from kivy.tools.packaging.pyinstaller_hooks import install_hooks

import kivy.core.video

2. You’ll need to include the gstreamer directory, found in the kivy distribution, in the COLLECT call.

You can specify the direct path, or get it from the environment. In addition, the contents of the

gstreamer/bin directory need to be included in the top level directory, otherwise the build process

may have trouble finding dlls (this will create a second copy of the contents of bin):

import os

gst_plugin_path = os.environ.get('GST_PLUGIN_PATH').split('lib')[0]

COLLECT(exe, Tree(...),

Tree(gst_plugin_path),

Tree(os.path.join(gst_plugin_path, 'bin')),

...)

Following is an example of how to bundle the videoplayer at

kivy27/examples/widgets/videoplayer.py. From kivy-2.7.bat. Create the VideoPlayer directory alongside kivy-2.7.bat:

cd VideoPlayer

pyinstaller --name gstvideo ..\kivy27\examples\widgets\videoplayer.py

Now edit the spec file. At the top of the file add:

import os

from kivy.tools.packaging.pyinstaller_hooks import install_hooks

import kivy.core.video

install_hooks(globals())

gst_plugin_path = os.environ.get('GST_PLUGIN_PATH').split('lib')[0]

Remove the hookspath=None parameter, and change:

coll = COLLECT(exe,

a.binaries,

...

to (remove the SDL2 part if SDL2 is not used):

coll = COLLECT(exe, Tree('../kivy27/examples/widgets'),

Tree([f for f in os.environ.get('KIVY_SDL2_PATH',

'').split(';') if 'bin' in f][0]),

Tree(gst_plugin_path),

Tree(os.path.join(gst_plugin_path, 'bin')),

Page 63: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 63

a.binaries,

...

This will include gstreamer and the example video files in examples/widgets. To build, run:

pyinstaller gstvideo.spec

Then you should find gstvideo.exe in VideoPlayer\dist\gstvideo, which when run will play a

video.

5. Tools/msi/msi.py.

I suggest to use the packaging tool that I also use to build the Python releases, which is in

Tools/msi/msi.py. Unpack the additional dependencies on top of the Python source (or an

installation), then adjust msi.py to pick up all additional files that you want to package. You

should adjust display strings to indicate that this is really a separate Python distribution.

6. Making executable Windows programs

https://pythonhosted.org/guiqwt/disthelpers.html

The py2exe Python library is an extension to Python distutils module which converts Python scripts into executable Windows programs, able to run without requiring a Python installation.

Making such an executable program may be a non trivial task when the script dependencies include libraries with data or extensions, such as PyQt4 or guidata and guiqwt. This task has been considerably simplified thanks to the helper functions provided by guidata.disthelpers.

G. Example

This example is included in guiqwt source package (see the py2exe_example directory).

Simple example script named simpledialog.pyw which is based on guiqwt (and implicitely on

guidata):

from guiqwt.plot import ImageDialog

from guiqwt.builder import make

class VerySimpleDialog(ImageDialog):

def set_data(self, data):

plot = self.get_plot()

item = make.trimage(data)

plot.add_item(item, z=0)

plot.set_active_item(item)

plot.replot()

if __name__ == "__main__":

import numpy as np

from guidata import qapplication

qapplication()

dlg = VerySimpleDialog()

dlg.set_data(np.random.rand(100, 100))

dlg.exec_()

The setup.py script may be written as the following:

from distutils.core import setup

import py2exe # Patching distutils setup

from guidata.disthelpers import (remove_build_dist, get_default_excludes,

get_default_dll_excludes,

create_vs2008_data_files,

add_modules)

Page 64: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 64

# Removing old build/dist folders

remove_build_dist()

# Including/excluding DLLs and Python modules

EXCLUDES = get_default_excludes()

INCLUDES = []

DLL_EXCLUDES = get_default_dll_excludes()

DATA_FILES = create_vs2008_data_files()

# Configuring/including Python modules

add_modules(('PyQt4', 'guidata', 'guiqwt'), DATA_FILES, INCLUDES,

EXCLUDES)

setup(

options={

"py2exe": {"compressed": 2, "optimize": 2, 'bundle_files':

1,

"includes": INCLUDES, "excludes": EXCLUDES,

"dll_excludes": DLL_EXCLUDES,

"dist_dir": "dist",},

},

data_files=DATA_FILES,

windows=[{

"script": "simpledialog.pyw",

"dest_base": "simpledialog",

"version": "1.0.0",

"company_name": u"CEA",

"copyright": u"Copyright © 2010 CEA - Pierre Raybaut",

"name": "Simple dialog box",

"description": "Simple dialog box",

},],

zipfile = None,

)

Make the Windows executable program with the following command:

python setup.py py2exe

Page 65: Python - Gregg Roetengreggroeten.com/Pub-Doc-Soft/Python-Django-PyCharm-Designer-doc.pdfDjango (Web Application Framework - WAF) ... settings.py files .html in templates/admin

pg 65

Appendix

Sources

This document was compiled from many resources including:

http://cyrille.rossant.net/create-a-standalone-windows-installer-for-your-python-application/