Feel free to ask questions. Raise your hand. Throw something.
Follow me on twitter @simeonfranklin
Or on my blog at http://simeonfranklin.com/blog/
Or come and find me organizing the Python community at http://sfpythonmeetup.com or http://baypiggies.net.
Aimed at a novice audience. I hope to:
Give a basic overview of Django
show you some of my favorite Django apps
Talk about advanced Python language features you should be using.
Feel free to ask questions. Raise your hand. Throw something.
(No heckling!)
So let’s oveview!
Django: A "web application framework"
Same space as competitors like Ruby on Rails, Pyramid etc.
Sucessfully used on large projects:
50K+ downloads of Django version 1.5 via PyPi
4,200+ sites listed on http://www.djangosites.org/
Not comprehensive by any means! I have worked on 100+ sites not listed there!
So, you want to build a web application.
Reddit and Pinterest are very different projects.
But both are at least partly:
HTML interfaces to highly dynamic data stored in a database.
What do we have to know?
Let’s see if we can understand this much.
See the documentation.
Basically:
$ virtualenv MYPROJECT $ source MYPROJECT/bin/activate (MYPROJECT)$ pip install django
A web application is a project.
Django comes with a tool to create a starting project for you.
$ django-admin.py startproject storytime $ find storytime/ storytime/ storytime/storytime storytime/storytime/settings.py storytime/storytime/urls.py storytime/storytime/__init__.py storytime/storytime/wsgi.py storytime/manage.py
A project contains:
We can use manage.py to start up a development server to view our web app!
$ python manage.py runserver Validating models... 0 errors found Django version 1.5.1, using settings 'storytime.settings' Development server is running at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
A project is made of many applications.
Django includes many built in apps in django.contrib for authentication, serving static files, security.
We need to create our own apps. The start page helpfully suggests we try:
$ python manage.py startapp story
Which results in some more files:
$ find story story story/views.py story/__init__.py story/tests.py story/models.py
The start page also helpfully told us to edit the settings file to specify a database. Sqlite drivers come with Python so I’ll just use that to start with…
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'storytime.sqlite3', } }
I also need to add my new application to my settings file’s INSTALLED_APPS directive:
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'story', )
The part after the domain.
All web frameworks: provide a way to map foo/ to some code to do something.
Django has us write regular expressions that map a url to a view.
from django.conf.urls import patterns, include, url urlpatterns = patterns('', # Examples: # url(r'^$', 'storytime.views.home', name='home'), # url(r'^storytime/', include('storytime.foo.urls')), )
This kinda sucks, especially for beginners!
Let’s write one url rule and understand it
from django.conf.urls import patterns, include, url urlpatterns = patterns('', url(r'^$', 'story.views.home', name='home'), )
For more details: see the excellent docs at https://docs.djangoproject.com/en/1.5/topics/http/urls/
A view is Python code that takes a `request` object and returns a `response` object.
Sound familiar?
from django.http import HttpResponse def home(request): return HttpResponse("Hello world!")
But… I don’t see any HTML!
Let’s make a base template with our "site design" in it.
$ mkdir -p story/templates/story $ touch story/templates/story/base.html
Let’s create a minimal html base template
<html> <head> <title>This is my web app!</title> </head> <body> <h1>Welcome to Storytime!</h1> {% block content %} {% endblock %} </body> </html>
Let’s create another template called home.html.
{% extends "story/base.html" %} {% block content %} {{ hello }} {% endblock %}
Oh yeah, the view!
from django.shortcuts import render_to_response def home(request): return render_to_response("story/home.html", {'hello': "Hello World!"})
You’re going to have to learn a bunch of tags and filters.
Don’t worry - they’re easy.
See https://docs.djangoproject.com/en/1.5/topics/templates/ and https://docs.djangoproject.com/en/1.5/ref/templates/builtins/
Models: database tables represented in Python code.
Your handle to:
Importantly:
A model class == Database table.
A model instance == a database table row
from django.db import models class Line(models.Model): text = models.CharField(max_length=255)
Django comes with a command to create the database structure for us:
$ python manage.py syncdb Creating tables ... Creating table auth_permission Creating table auth_group_permissions Creating table auth_group Creating table auth_user_groups Creating table auth_user_user_permissions Creating table auth_user Creating table django_content_type Creating table django_session Creating table django_site Creating table story_line
Now that we’ve got a database created for our models let’s try using the interactive Python console to play with them.
$ python manage.py shell >>> from story.models import Line >>> line = Line(text="There once was a girl who had a blue hat.") >>> line.save()
That’s all the Python code it takes to create a new row in our database. We can also query our database.
>>> Line.objects.all() [<Line: Line object>]
Maybe we should update the view again!
from django.shortcuts import render_to_response from .models import Line def home(request): return render_to_response("story/home.html", {'lines': Line.objects.all()})
And the template
{% extends "story/base.html" %} {% block content %} <ul> {% for line in lines %} <li style="color:{% cycle 'blue' 'green' %}">{{ line.text }}</li> {% endfor %} {% endblock %}
As usual see the excellent docs.
https://docs.djangoproject.com/en/1.5/topics/db/models/ and https://docs.djangoproject.com/en/1.5/topics/db/queries/
You can enable the built-in admin app by uncommenting a couple lines in the urls.py, the settings.py, and by adding an admin.py file to your application.
from django.contrib import admin from .models import Line admin.site.register(Line)
I can use this interface to edit my data.
And the data shows up on my web page.
You’ve just written your first web app
Of course there’s much, much more needed.
Django is a big framework.
There are lots of batteries included.
(the PDF download of the docs is 1200+ pages)
Because apps are a fundamental piece in Django.
Following are my top 10 apps.
I could totally do a top 20.
I’ll be brief.
database migrations.
Coming soon to django.contrib thanks to a $20k fund raising round on Kickstarter!
How the heck did I get to this page?
Developer Goodies:
API to multiple backend search engines.
Easily create RESTful api for your Django models.
This is a big one.
Spin off tasks to separate worker processes.
Can I just punt on explaining this?
Resize images from template tags
<img src="{% thumbnail profile.photo 50x50 %}" alt="" />
Edit history and undo for your models with admin support.
A prettier admin skin. Plus cool stuff like:
You get the idea.
Tons of high quality apps to handle
Got an idea?
Build a redistributable app so you can share your idea!
And Djangoic. Djangoish? Djangonical?
Make it look like Django!
Django is not magic.
It does use advanced Python language features to provide a clean API.
For instance:
Django likes to use a declarative class to configure things.
class Line(models.Model): text = models.CharField(max_length=255)
class RegistrationForm(forms.Form): username = forms.CharField(max_length=30) email = forms.EmailField(label="E-mail")
class PollForm(ModelForm): class Meta: model = Poll
class UserResource(ModelResource): class Meta: queryset = Users.objects.all() resource_name = "user"
I could keep going.
Haystack Indexes.
Django sitemaps.
They all look alike
Declarative classes whose class attributes are instances of a related type.
Models have ModelFields, Forms have FormFields, etc.
The Class you build is just configuration for building some other more powerful object.
This style is enabled by a feature called metaclasses in Python.
The ability to have the apparently normal instanciation of a class do something completely different.
Deep dark magic!
No!
Just a powerful language feature.
This is deeper than we can go in [fill in X remaining here] minutes.
Let’s try another example.
If you’ve done a little Django you’ve bumped into the login_required decorator.
from django.shortcuts import render_to_response from django.contrib.auth.decorators import login_required from .models import Line @login_required def home(request): return render_to_response("story/home.html", {'lines': Line.objects.all()})
Just add @login_required above your view.
Pretty cool.
Gonna move fast, see http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/ for a much slower paced introduction if this is your first exposure to decorators.
A decorator is a function that takes function and returns a function in its place.
library = {} def register(f): library[f.__name__] = f return f @register def myfunc(): pass
The library variable looks like:
{'myfunc': <function myfunc at 0x9064e2c>}
OH - that’s exactly how Django keeps track of your custom template tags/filters!
Yup. Not magic. Just Python.
Our views frequently need to return a RequestContext.
Basically this lets Django provide access to a lot of variables like the current user to the template, automatically.
We could do this manually in our view:
from django.shortcuts import render_to_response from django.template import RequestContext from django.contrib.auth.decorators import login_required from .models import Line @login_required def home(request): return render_to_response("story/home.html", {'lines': Line.objects.all()}, context_instance=RequestContext(request))
I hate that last line.
We could use a better shortcut: render automatically builds a request context for us.
from django.shortcuts import render from django.contrib.auth.decorators import login_required from .models import Line @login_required def home(request): return render(request, "story/home.html", {'lines': Line.objects.all()})
That’s better. But what about using a decorator to make this view really simple?
from django.shortcuts import render class Render(object): def __init__(self, template): self.template = template def __call__(self, function): self.function = function def wrapper(request, *args): ctx = self.function(request, *args) return render(request, self.template, ctx) return wrapper
Take a minute:
Now our view looks like:
from django.contrib.auth.decorators import login_required from .models import Line from .shortcuts import Render @login_required @Render("story/home.html") def home(request): return {'lines': Line.objects.all()}
Cool?
All this leads me to my point. How do I get better at Django?
practice. Write different types of apps
read the docs. All of them. (All links on the front page at least. Start at the tutorial.)
Get better at Python
Come see us at http://marakana.com/
/
#