Outline
- Background: Django, goals, prerequisites
- The Food and Farm Finder (F3) Task
- Building the app
- Views
- Data and models
- Templates
- Wrap-up
Goals
Introduce the basics of Django, focusing on ...
- Interactively building a database-backed web site (during this talk!)
- Handle a variety of HTTP requests in a general fashion
- Create a data model and database implementation
- Create alternate views of that data
- Create a collection of HTML pages and responses
- Can I do all this in
60 45 minutes?!?
Why Django?
Django: the Web framework for perfectionists with deadlines
- Builds on Python:
- Clean, elegant, object-oriented language
- Dynamic typing and interactive evaluation are well suited to rapid prototype development
- Rich set of library modules and an active open-source community
- Born in the high-pressure world of on-line publications
- Well-suited to database-backed tasks
- Popular, well-supported
- Automate the drudgery and focus on the fun!
Prerequisites
- 0 Django knowledge
- Python: basic syntax, classes and methods, regexps
- Basic understanding of web architecture and development
- Basic understanding of relational data models
- A little HTML
- Optional: track shoes
Shortcuts: What I'm Leaving Out
- Python installation
- Download from python.org or ActiveState
- I'll be using Python 2.5 today: 2.4 or 2.6 should work the same. Django is not yet compatible with Python 3.
- Django installation
- Database installation
- Python 2.5+ comes with SQLite, so no extra installation is required
- I'm using MySQL today: this also requires the MySQLdb database connector. It can be hard to find Windows binaries for this.
- Database configuration for Django
- Creating a new project:
django-admin.py startproject mysite
- Edit variables in
settings.py
for db engine, name, username, password
python manage.py syncdb
- Data: i've already modeled and organized it
- Hosting issues and deployment on an external web server
- These are all documented but tedious: let's focus on the fun parts!
The Application: F3
Whatcom Food and Farm Finder from Sustainable Connections
- Several dozen local farms, with detailed descriptions, contact information
- A wide variety of foods and other products, with information about seasons
- But ... Dead Tree Deficiencies!
- Wouldn't it be great if you could easily
- Search this information
- Plot the locations on a Google Map
- Mash this data up with other resources
- Support eating healthy and buying local
The Application: F3 (2)
- What it would take to make a Django app out of this?
- Capture the data in a structured fashion
- Create useful models and views of them
- Put it up on the web for everybody
- Disclaimer: this is a rogue data operation!
- No endorsement or approval from Sustainable Connections is expressed or implied.
The Source Data: Farms
The Source Data: Berries
Data Elements of F3
- 70 instances of Food: name, type, month that it's available
- Month: name, integer
- FoodType (berries, plants, vegetables, etc.): name
- 64 instances of Farm: name, contact, address, etc.
- ServiceOffering (farm stand, u-pick, etc.): name, description
- SustainabilityIndicator (green power, zero waste, organic, etc.): name, description
- PaymentMethod: name
Building the App: startapp
Building the App: Our First View
- We'll add a simple view to
f3_0.views.py
from django.http import HttpResponse
def pingfn(request):
return HttpResponse('Hello LinuxFest!')
- Then wire a URL to it in the project-level
urls.py
import f3_0.views
urlpatterns = patterns('',
(r'^ping/', f3_0.views.pingfn),
)
- This will dispatch the URL
(appsite)/ping
to call pingfn()
, supplying the HTTP request as an argument.
Building the App: Testing Our First View
Review of our First App
- We now have a complete initial system that can:
- Receive a URL
- Dispatch to a function
- Generate a response
- We can test it interactively on our development server
- Pretty unimpressive, but this demonstrates the basic HTTP interface
The Database Layer
- Django is designed for database-driven web sites
- The data layer includes Python-based object models, and a database API
- Model-View-Controller, Model-Template-View ... whatever
- Lots of acceleration thanks to Django models:
- You get to work in Python instead of SQL
- Django can generate table definitions, manage indexes, provide auto-incremented primary keys, and more
- Your app can be database-agnostic
Defining Models: FoodType
, Month
import django.db.models as m
class FoodType(m.Model):
name = m.CharField(max_length=30, unique=True)
def __unicode__(self):
return self.name
class Month(m.Model):
name = m.CharField(max_length=10, unique=True,
help_text="the month")
order = m.IntegerField(unique=True)
def __unicode__(self):
return self.name
Defining Models: Food
class Food(m.Model):
name = m.CharField(max_length=50, unique=True,
help_text="the name of the food")
type = m.ForeignKey('FoodType')
months = m.ManyToManyField('Month')
def __unicode__(self):
return self.name
- Many
Food
instances can have the same type
- The relationship between
Food
instances and Month
instances is many-to-many
Defining Models: Farm
(Abbreviated)
class Farm(m.Model):
name = m.CharField(max_length=100)
contact_person = m.CharField(max_length=100)
address = m.TextField()
phone_number = m.CharField(max_length=30)
website = m.URLField()
email_address = m.EmailField()
description = m.TextField()
hours_of_operation = m.CharField(max_length=100)
seasonal_operation = m.CharField(max_length=100)
service_offerings = m.ManyToManyField('ServiceOffering')
payment_methods = m.ManyToManyField('PaymentMethod')
sustainability_indicators = m.ManyToManyField('SustainabilityIndicator')
categories = m.ManyToManyField('FarmCategory')
confirmed_foods = m.ManyToManyField('Food')
Loading Data
import django.core.serializers as ser
for obj in ser.deserialize("json", open('f3_final.json', 'r')):
obj.save()
- Django has built-in serialization and deserialization
- Our source data is formatted as JSON
A Snippet of Data in JSON
{ "pk": 49,
"model": "f3_final.farm",
"fields": {
"phone_number": "360.380.2699",
"website": "http://www.boxxberryfarm.com",
"name": "Boxx Berry Farm",
"confirmed_foods": [9, 8, 2, 13, 46, 60],
"service_offerings": [1, 5, 6],
"hours_of_operation": "",
"seasonal_operation": "",
"payment_methods": [],
"address": "6211 Northwest Road\nFerndale",
"sustainability_indicators": [1],
"contact_person": "Mike & Roger Boxx",
"email_address": "",
"categories": [],
"description": ""
}},
Database API: Simple Query
>>> from f3_final.models import *
>>> bbf = Farm.objects.get(id=49)
>>> bbf
<Farm: Boxx Berry Farm>
>>> bbf.website
u'http://www.boxxberryfarm.com'
>>> FoodType.objects.all()
[<FoodType: Berries>, <FoodType: Dairy Products>,
<FoodType: Eggs> ... ]
- Basic equivalents of SQL
SELECT
Database API: Other Queries
>>> Month.objects.filter(name__contains='r')
[<Month: January>, <Month: February>,
<Month: March>, <Month: April>, <Month: September>,
<Month: October>, <Month: November>, <Month: December>]
>>> Food.objects.filter(type__name='Berries')
[<Food: Blackberries>, <Food: Blueberries>,
<Food: Boysenberries> ... ]
- You can chain through data relationships
- Filters can be pipelined
More Data Layer Functionality
- Create and save new records
- Modify values
- Delete records
QuerySet
s provide lazy evaluation and caching.
- Manager methods provide table-level functionality
Template Basics
- Django separates views from the HTML that displays them:
- You should be able to change page design without touching code
- Different people have different gifts
- Each can be developed separately
- The template system provides basic HTML plus variables, control tags, and filters
- You don't have to use it
- You can generate more than just HTML
My First Template
<html>
<head><title>My First Template</title></head>
<body>
<h1></h1>
{% if object_list %}
<table>
<thead><tr><th>ID</th><th>Name</th></tr></thead>
<tbody>
{% for object in object_list %}
<tr>
<td>{{ object.id }}</td>
<td>{{ object.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</body>
</html>
Rendering Views with Templates
- Retrieve data
- Define the context information the template will need:
- Contexts let you further isolate template design from data details
- Hand off to a template to render it
- The template system uses
.
to access dictionary keys, attributes, methods (without argument), and list indices
- Non-existent variables are rendered as empty strings and fail silently
Putting It All Together: f3_final
- Tell the project-level
urls.py
to dispatch to app-specific URLs
import f3_0.views
urlpatterns = patterns('',
(r'^f3/', include('lfnw.f3_final.urls')))
- Define a pattern in
f3_final/urls.py
to show a list of farms
import views
urlpatterns = patterns('',
(r'^farms/$', views.farms_list))
Putting It All Together: f3_final
(2)
- Write the view
from django.shortcuts import render_to_response
import f3_final.models as models
def farms_list(request):
return render_to_response('myfirsttemplate.html',
{'object_list': models.Farm.objects.all(),})
(render_to_response
instantiates a template object with the given context and generates an HTTP response)
- Try it out: http://127.0.0.1:8000/f3/farms
Admin Interface
- More batteries included: a powerful admin interface for free!
- Includes display customization, entry validation, drop-downs, filtering, ...
- To enable it:
- Add it to your
INSTALLED_APPS
- Run
python manage.py syncdb
- Uncomment the relevant lines in
urls.py
- To use it:
- Add an
admin.py
file to the app
- Register models you want an admin interface for
Review: The Django Development Cycle
- Define the resources your app will expose
- Model those resources in the data layer
- Design the URLs for those resources
- Define views that query the models and provide operational logic
- Design templates to display the views
- Lather, rinse, repeat, have fun ...
What Else Can Django Do?
- Errors pages for debugging
- 404 handling, custom 404 responses
- Template inclusion to provide standard styles
- ... and much, much more
Best Practices for Speedy Django Development
- Leverage the power of interactive, incremental development
- Remember it's all "just Python"
- Keep things decoupled
- Cut with the grain, not against it:
- Let Django manage the database interactions
- Use the template system
- The Django community is very helpful: use it!
And Now, a Word from our Sponsors ...
Resources
- Bitbucket repository for Django code and data
- If you like Django, check out James Tauber's Pinax: layers social networking and other features on top of Django