Introduction to Django
- 1. Django is a high-level Python Web framework that encourages rapid development
and clean, pragmatic design.
True! (it enocourages, doesn't force you)
● Object Relational Mapper
● Automatic Admin Interface
● URL dispatcher
● Template System
● Cache System
● Internationalisation
● Forms, with data validatio0n
● devlopment web server
- 2. Django - overview
Typical scenario
urls.py
views.py
request models.py
request
web
client server
response Database
response
(normally html)
- 3. models.py
● This is the file that
defines the objects / Poll Choice
ralationships. Django
equivalent of SQL
'create table'
commands.
● Can also define
instance methods – from django.db import models
that act on one
class Poll(models.Model):
instance of the object. question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
- 4. models.py
Poll Choice
from django.db import models
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_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
[user]$ python manage.py synchdb
BEGIN;
CREATE TABLE "polls_poll" (
"id" serial NOT NULL PRIMARY KEY,
"question" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
CREATE TABLE "polls_choice" (
"id" serial NOT NULL PRIMARY KEY,
"poll_id" integer NOT NULL REFERENCES "polls_poll" ("id") DEFERRABLE INITIALLY DEFERRED,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL
);
COMMIT;
- 5. Now we have an API to play with!
This saves writing a lot of
boiler plate SQL code, e.g.
[user]$ python manage.py shell
INSERT's, UPDATE's, etc
>>> from polls.models import Poll, Choice # Import the model classes we just wrote.
# No polls are in the system yet.
>>> Poll.objects.all()
[]
# Create a new Poll.
>>> from django.utils import timezone
>>> p = Poll(question="What's new?", pub_date=timezone.now())
>>> p.save()
# 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.
>>> p.id
1
# Access database columns via Python attributes.
>>> p.question
"What's new?"
>>> p.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
# Change values by changing the attributes, then calling save().
>>> p.question = "What's up?"
>>> p.save()
# objects.all() displays all the polls in the database.
>>> Poll.objects.all()
[<Poll: Poll object>]
- 6. Admin Interface
“One of the most powerful parts of Django is the automatic admin interface. It reads metadata
in your model to provide a powerful and production-ready interface that content producers can
immediately use to start adding content to the site. In this document, we discuss how to
activate, use and customize Django’s admin interface.”
● One of Django's best features.
● Provides a web page to view / enter / update
data, one per model (one per database table).
● Automatically generated.
● Lots of configuartion options.
● Probably able to do a large chunk of what you
want to do (for little effort)
- 7. admin.py
from polls.models import Poll, Choice
from django.contrib import admin
class ChoiceInline(admin.TabularInline):
model = Choice
extra = 3
class PollAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
list_display = ('question', 'pub_date', 'was_published_today')
list_filter = ['pub_date']
search_fields = ['question']
date_hierarchy = 'pub_date'
inlines = [ChoiceInline]
admin.site.register(Poll, PollAdmin)
- 8. Django - overview
urls.py
views.py
request models.py
request
web
client server
response Database
response
(normally html)
- 9. urls.py
● This is the file that tells django what code to execute based on the
url
● Uses regular expressions, and passes caturing groups to the view
from django.conf.urls.defaults import *
from django.conf.urls.static import static
from django.conf import settings
from sequencing import views
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'admin/sequencing/lookup_values/(?P<table>S+)/(?P<field>S+)/' ,
'sequencing.views.lookup_values'), # goes to lookup_values
# in views.py, with paramters,
# self, table, and field
(r'^admin/dates_view/' , DatesView.as_view()) , # example of a generic list view
)
- 10. views.py
● So each view will take an HTTP request object, and return a HTTP
response.
● Usually you will return HTML, but other responses such as JSON or
excel can be returned.
A very basic example:
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the poll index.")
- 11. views.py and models.py together
from django.http import HttpResponse
from polls.models import Poll # importing Poll object from models.py
def index(request):
latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
output = ', '.join([p.question for p in latest_poll_list])
return HttpResponse(output)
This line will generate SQL equivalent to:
SELECT * FROM myapp__poll
ORDER BY pub_date DESC
LIMIT 5
- 12. Django - overview A view
usually
generates a
queryset
urls.py (from
models), and
views.py passes it to a
template to
generate a
request models.py response
request
web
client server
response Database
(normally html)
response
- 13. views using a template
views.py
from django.http import HttpResponse
from django.template import Context, loader
from polls.models import Poll
def index(request):
latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
template = loader.get_template('polls/index.html')
context = Context({
'latest_poll_list': latest_poll_list,
})
return HttpResponse(template.render(context))
polls/index.html
{% if latest_poll_list %}
<ul>
{% for poll in latest_poll_list %}
<li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
- 14. Good Bad
● Very well doccumented ● ORM is somehwat limted. For example
no contidtional agrregates.
● Well known, lots of answers on Stack
Overflow ● Template system is somewhat imited, no
logic in templates.
● Lots of third party 'apps' (plugins), e.g
Tastypie for REST, Django Debug ● These things can be replaced, but then
Toolbar, CMS pugins you loose a lot of the magic that makes
it so great. For example replacing the
● (Semi) automatically generated Admin ORM with SQL alchemy is possible, but
interface. May do most of what you need then you loose the Admin interface.
for very little effort (just configuration).
● Schema changes are a bit of a pain
(though to be fair, probably the same for
any DB application). South application
helps here.
so-so
● Deployment is not as easy as PHP,
but there are a few options.
● Hosting not as ubiqutous. Though this
is true for any Python framework