Table of Contents
django
Resources
- Quick start: https://code.djangoproject.com/wiki/DjangoCheatSheet
-
Install Django
We will install django on home ~ dir.
mkdir ~/src cd ~/src wget http://www.djangoproject.com/download/1.3.1/tarball/ -O django.tar tar xvf django.tar cd Django-1.3.1
Install python and django in a specific directory. This will create bin & lib containing python&django in specified directory.
python setup.py install --home=~/devfs/opt/
Or install django on system's python directory (preferred):
sudo python setup.py install
This will install django to
[td@td-fed tutorial]$ ls /usr/lib/python2.7/site-packages/django/
set the PYTHONPATH env variable:
export PYTHONPATH=$HOME/lib/python export PATH=$HOME/bin:$PATH
Now verify that Django is installed and the right version is in your path:
python >>> import django >>> print django.get_version() 1.3.1
Virtualenv
Virtualenv/Sandbox for python env to provide consistent project settings.
Prerequisites
yum install python-pip.noarch yum install python-virtualenv.noarch
Enter virtualenv
$ virtualenv mysite-env $ source mysite-env/bin/activate (mysite-env)$
Install python packages
(mysite-env)$ pip install Pinax
Creating a project NOTE: changed from django 1.4
obsolated!!! see https://github.com/ryanrdetzel/django-base-template
source: django tutorials.
Start Project:
$django-admin.py startproject mysite
Run webserver:
$python manage.py runserver
Configure Database:
$vim mysite/settings.py ... edit DATABASE section...
Create tables:
$python manage.py syncdb
Reset database for an app
reset and sqlreset were both just wrappers around other management commands. sqlreset in particular can be duplicate by simply running:
python manage.py sqlclear myapp python manage.py sqlall myapp
reset only served to automatically run the result of sqlreset on the database. Personally, I think removing that is a fantastic idea. Still, if you want similar functionality, you can just pipe the output to your database's shell commands.
For PostgreSQL, for example:
python manage.py sqlclear myapp | psql mydatabase python manage.py sqlall myapp | psql mydatabase
Dynamic Web Page
View
Dynamimc web page is generated by view functions (view for short). A view function is a python function that takes a web request and return a web response. This response can be a HTML content of a page, or a redirect, or a 404 error, or an XML document, or an image… or anything.
The view itself contains whatever arbitrary logic it needs to return the response. It can live anywhere in Python path.
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
Mapping URLs to views
The URLconf maps url patterns to view functions. Views must be on Python path. URLconf is configured in urls.py.
from django.conf.urls.defaults import *
# make view function available in urls.py modul.
from mysite.views import current_datetime
urlpatterns = patterns('',
# define a maping (pattern, view).
(r'^time/$', current_datetime),
)
The patterns function
patterns(prefix, pattern_description, ...)
A function that takes a prefix, and an arbitrary number of URL patterns, and returns a list of URL patterns in the format Django needs.
The first argument to patterns() is a string prefix. See The view prefix below.
The remaining arguments should be tuples in this format:
(regular expression, Python callback function [, optional dictionary [, optional name]])
Pass extra options to view functions
# urls.py
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}),
(r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}),
)
# views.py
from django.shortcuts import render_to_response
from mysite.models import MyModel
def foobar_view(request, template_name):
m_list = MyModel.objects.filter(is_new=True)
return render_to_response(template_name, {'m_list': m_list})
The dictionary is passed to view function by the patterns function.
Passing dictionary is a future of python language:
'arg & ''*kwarg
The special syntax, *args and **kwargs in function definitions is used to pass a variable number of arguments to a function. The single asterisk form (*args) is used to pass a non-keyworded, variable-length argument list, and the double asterisk form is used to pass a keyworded, variable-length argument list. Here is an example of how to use the non-keyworded form. This example passes one formal (positional) argument, and two more variable length arguments.
def test_var_args(farg, *args):
print "formal arg:", farg
for arg in args:
print "another arg:", arg
test_var_args(1, "two", 3)
def test_var_kwargs(farg, **kwargs):
print "formal arg:", farg
for key in kwargs:
print "another keyword arg: %s: %s" % (key, kwargs[key])
test_var_kwargs(farg=1, myarg2="two", myarg3=3)
Calling a function:
def test_var_args_call(arg1, arg2, arg3):
print "arg1:", arg1
print "arg2:", arg2
print "arg3:", arg3
args = ("two", 3)
test_var_args_call(1, *args)
def test_var_args_call(arg1, arg2, arg3):
print "arg1:", arg1
print "arg2:", arg2
print "arg3:", arg3
kwargs = {"arg3": 3, "arg2": "two"}
test_var_args_call(1, **kwargs)
source: http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/
How Django process a request?
ROOT_URLCONF is defined in settings.py which points to a urls.py file that defines the mappings. When a request comes in e.g: /time/, Django loads the root urls.py and looks for matching url pattern. If one is found, it calls the view function associated with the pattern, passing an HttpRequest object as first parameter to the function. The view function returns HttpResponse object.
URLconf makes Django's view and url definitions loosely coupled.
404 errors
Wildcard URLpatterns
from django.conf.urls.defaults import *
from mysite.views import current_datetime, hours_ahead
urlpatterns = patterns('',
(r'^time/$', current_datetime),
(r'^time/plus/\d+/$', hours_ahead),
)
Regex can be used to describe url patterns. Here the url can be /time/plus/2/ or /time/plus/9999/. The url will be handled by 'hours_ahead' function:
def hours_ahead(request, offset): offset = int(offset) dt = datetime.datetime.now() + datetime.timedelta(hours=offset) html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt) return HttpResponse(html)
The view function takes 2 parameters. The first one is the HttpRequest. The second one is offset, the string captured from the request url. 'offset' will take the value of '\d+'. 'offset' is just the name of the parameter and can be anything else. It still gets the value from request url as long as it is placed after 'request'.
Django template system
Template system basic
Using the template system
There are two steps to use template.
- Create a template by providing raw template code as a string. Django also offers a way to import a file containing the template code.
- Call the render() method of the Template object with a given set of variables (context…). This returns a rendered template as a string with all the variables and block tags evaluated according to the context.
Creating and rendering template
>>>from django.template import Context, Template
>>>t = Template("My name is {{ name }}.")
>>>c = Context({"name": "Stephane"})
>>>t.render(c)
My name is Stephane.'
Context variables lookup
When a dictionary is passed to python, use 'dot' to access the values in that dictionary.
>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> c = Context({'person': person})
>>> t.render(c)
'Sally is 43 years old.
'dot' can also be used to:
- access attributes of object.
>>> from django.template import Template, Context
>>> class Person(object):
...
def __init__(self, first_name, last_name):
...
self.first_name, self.last_name = first_name, last_name
>>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
>>> c = Context({'person': Person('John', 'Smith')})
>>> t.render(c)
'Hello, John Smith.
- call methods of an object: <code>from django.template import Template, Contextt = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')t.render(Context({'var': 'hello'}))
'
hello – HELLO – False'
t.render(Context({'var': '123'}))'
123 – 123 – True' </code>
Note: do not include “()” in the method. It also not possible to pass argument to the methods. Only method with no arguments can be called.
Basic template tags and filters
Tags
{% if athlete_list and coach_list %}
Both athletes and coaches are available.
{% endif %}
{% if not athlete_list %}
There are no athletes.
{% endif %}
{% if athlete_list or coach_list %}
There are some athletes or some coaches.
{% endif %}
{% if not athlete_list or coach_list %}
There are no athletes or there are some coaches. (OK, so
writing English translations of Boolean logic sounds
stupid; it's not our fault.)
{% endif %}
{% if athlete_list and not coach_list %}
There are some athletes and absolutely no coaches.
{% endif %}
For loop
{% for athlete in athlete_list reversed %}
...
{% endfor %}
It’s possible to nest {% for %} tags:
{% for country in countries %}
<h1>{{ country.name }}</h1>
<ul>
{% for city in country.city_list %}
<li>{{ city }}</li>
{% endfor %}
</ul>
{% endfor %}
For loop magic variables
- forloop.counter
- forloop.counter0 is like forloop.counter, except it’s zero-indexed.
- forloop.revcounter
- forloop.revcounter0
- forloop.first
- forloop.last
<code> {% for link in links %}link{% if not forloop.last %} | {% endif %}➥ {% endfor %} </code>
- forloop.parentloop
{% for country in countries %}
<table>
{% for city in country.city_list %}
<tr>
<td>Country #{{ forloop.parentloop.counter }}</td>
<td>City #{{ forloop.counter }}</td>
<td>{{ city }}</td>
</tr>
{% endfor %}
</table>
{% endfor %}
ifequal/ifnotequal
{% ifequal section 'sitenews' %}
<h1>Site News</h1>
{% else %}
<h1>No News Here</h1>
{% endifequal %}
Only template variables, strings, intergers, decimal numbers are allowed as arguments to {% ifequal %}. Other types of variables can not be hardcoded in {% ifequal %}.
Comments
{# This is a comment #}
Filters
Filter is the simple way of altering the value of variables before they are displayed.
{{ my_text|escape|linebreaks }}
{{ bio|truncatewords:"30" }}
escape
escape: Escapes ampersands, quotes, and angle brackets in the given string. This is use- ful for sanitizing user-submitted data and for ensuring data is valid XML or XHTML. Specifically, escape makes these conversions:
- Converts & to &
- Converts < to <
- Converts > to >
- Converts “ (double quote) to "
- Converts ' (single quote) to '
length
returns the length of any value that object that has a len() method.
Using templates in view
Embedded template.
from django.template import Template, Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
t = Template("<html><body>It is now {{ current_date }}.</body></html>")
html = t.render(Context({'current_date': now}))
return HttpResponse(html)
Saving template in a file somewhere in the file sytem and using Python's file-open-functionality to read the content of the template.
from django.template import Template, Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
# Simple way of using templates from the filesystem.
# This doesn't account for missing files!
fp = open('/home/djangouser/templates/mytemplate.html')
t = Template(fp.read())
fp.close()
html = t.render(Context({'current_date': now}))
return HttpResponse(html)
Template loading
Template files are put in 'template dir', which is set in settings.py.
TEMPLATE_DIRS = (
"/home/html/templates/lawrence.com",
"/home/html/templates/default",
)
Django has two ways to load templates from files:
django.template.loader.get_template(template_name)
get_template returns the compiled template (a Template object) for the template with the given name. If the template doesn't exist, it raises django.template.TemplateDoesNotExist.
django.template.loader.select_template(template_name_list)
selecttemplate is just like gettemplate, except it takes a list of template names. Of the list, it returns the first template that exists.
Subdirectory can also be specified as parameter.
get_template('news/story_detail.html')
Custom template tags and filters
Code layout
Custom tags and filters can be defined in a py file and loaded using {% load %} tag.
Let's say the definitions for tags are in pollextras.py file: <code> polls/ models.py templatetags/ init.py pollextras.py
views.py
</code>
This line will make the tags available in a template file:
{% load poll_extras %}
To be a valid tag library, the module must contain a module-level variable named register that is a template.Library instance, in which all the tags and filters are registered. So, near the top of your module, put the following:
from django import template register = template.Library()
Writing filters
Writing tags
The template system works in a two-step process: compiling and rendering. To define a custom template tag, you specify how the compilation works and how the rendering works.
When Django compiles a template, it splits the raw template text into nodes. Each node is an instance of django.template.Node and has a render() method. A compiled template is, simply, a list of Node objects. When you call render() on a compiled template object, the template calls render() on each Node in its node list, with the given context. The results are all concatenated together to form the output of the template.
Thus, to define a custom template tag, you specify how the raw template tag is converted into a Node (the compilation function), and what the node's render() method does.
Writing the compilation function
the tag should be used like this:
<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>
The parser for this function should grab the parameter and create a Node object:
from django import template
def do_current_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError("%r tag requires a single argument" % token.contents.split()[0])
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % tag_name)
return CurrentTimeNode(format_string[1:-1])
Writing the renderer
The second step in writing custom tags is to define a Node subclass that has a render() method.
Continuing the above example, we need to define CurrentTimeNode:
from django import template
import datetime
class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = format_string
def render(self, context):
return datetime.datetime.now().strftime(self.format_string)
Notes:
- init() gets the formatstring from docurrenttime(). Always pass any options/parameters/arguments to a Node via its init(). * The render() method is where the work actually happens. render() should never raise TemplateSyntaxError or any other exception. It should fail silently, just as template filters should. Ultimately, this decoupling of compilation and rendering results in an efficient template system, because a template can render multiple contexts without having to be parsed multiple times. === Registering the tag === Finally, register the tag with your module's Library instance, as explained in “Writing custom template filters” above. Example: register.tag('currenttime', docurrenttime)
The tag() method takes two arguments:
- The name of the template tag – a string. If this is left out, the name of the compilation function will be used.
- The compilation function – a Python function (not the name of the function as a string).
As with filter registration, it is also possible to use this as a decorator:
@register.tag(name="current_time")
def do_current_time(parser, token):
...
@register.tag
def shout(parser, token):
...
If you leave off the name argument, as in the second example above, Django will use the function's name as the tag name.
Get dirty
Create Model:
python manage.py startapp polls ...edit polls/model.py...
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice = models.CharField(max_length=200)
votes = models.IntegerField()
Activate model:
Edit settings.py, add 'polls'.
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
# 'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'polls',
)
See SQL code for 'polls':
python manage.py sql polls
Play around
- python manage.py validate – Checks for any errors in the construction of your models.
- python manage.py sqlcustom polls – Outputs any custom SQL statements (such as table modifications or constraints) that are defined for the application.
- python manage.py sqlclear polls – Outputs the necessary DROP TABLE statements for this app, according to which tables already exist in your database (if any).
- python manage.py sqlindexes polls – Outputs the CREATE INDEX statements for this app.
- python manage.py sqlall polls – A combination of all the SQL from the sql, sqlcustom, and sqlindexes commands.
Update DB:
python manage.py syncdb
Python API:
python manage.py shell >>> from polls.models import Poll, Choice ...see django cheatsheet for DB built-in functions... ...type Poll + <tab> to see how you can start... cool!!
Working with models
- function unicode()
It's important to add unicode() methods to your models, not only for your own sanity when dealing with the interactive prompt, but also because objects' representations are used throughout Django's automatically-generated admin.
- str()?
class Poll(models.Model):
*** use <spaces> not <tabs> or python will throws unexpected indentation.
*** vim's :retab is useful for this.
# ...
def __unicode__(self):
return self.question
class Choice(models.Model):
# ...
def __unicode__(self):
return self.choice
- mycustomfunction()
import datetime
from django.utils import timezone
# ...
class Poll(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
Notes
django-filer cmsplugin_filer_image
http://django-filer.readthedocs.org/en/0.9.2/installation.html#subject-location-aware-cropping
https://github.com/crooksey/CMS-Image-Plugin/tree/master/arkestra_image_plugin
Template: namespace not defined, reverse
Implicitly define namespace
Source: http://stackoverflow.com/questions/2126489/anyone-knows-good-django-url-namespaces-tutorial
(r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')),
Separate urlpatterns in main urls.py:
not tried
urlpatterns = patterns('help',
url(r'^help/', include('apps.help.urls', namespace='help', app_name='help')),
)
urlpatterns += patterns('otherhelp',
url(r'^ineedhelp/', include('apps.help.urls', namespace='otherhelp', app_name='help')),
)
Using namespace
In template.html
Include this for django version < 1.5:
{% load url from future %}
Then refer to url like this: namespace:method
<form action="{% url 'openideas:vote' idea.id %}" method="post">
In views.py a.k.a reverse
return HttpResponseRedirect(reverse('openideas:results', args=(idea.id,)))
resources
- Django tutorials.
- The ddefinitive guide to web development done right.