Django : building a Python web app¶
- Django : building a Python web app
INTRODUCTION¶
- Presentations
- Davin Baragiotta
- Montréal-Python (MP, sprints/hackathons, workshops, PyCon)
- Sponsors
- Objectives
- know the architecture of a project : main files
- manage data in the admin backend
- present data in the frontend
- Documentation
- doc : good version of Django
- official : https://docs.djangoproject.com/en/1.4/
- French : http://docs.django-fr.org/
- tutorial
- Part 1 : create a project, create an app, play with ORM (API)
covered here - Part 2 : backend (admin)
covered here - Part 3 : frontend
covered here, even more straightforward ;)_ - Part 4 : forms and generic views
not covered here
- Part 1 : create a project, create an app, play with ORM (API)
- doc : good version of Django
- Technical setup
>>> import django >>> django.get_version() '1.4' >>> import south >>> south.__version__ '0.7.4.'
- Python >= 2.5
- Django 1.4
- Mac OS X : see tutorial Part 1 for extra config
- South 0.7.4 (optional)
PART 1 : WEB DEVELOPMENT WITH DJANGO : ARCHITECTURE OF A PROJECT¶
Web development¶
- schema : web development
- web framework's role : help to build a response to a request
- environments
- development (DEV)
- deployment (TEST, PROD)
Django¶
Why Django vs other framework (e.g.: CherryPy, Pyramid, web2py)- all-in-one
- admin : best-seller ;)
- docs
- community : widespread use
- urls.py
- views.py
- models.py
- templates (HTML)
- admin.py
Project : requirements¶
Montréal-Python has a rugby league (not true : DoesNotExist).
They contact you for a website that could manage the players and the teams...
... as well as plan the matches for the season.
Project : modeling¶
- Team
- Player
- Season
- Match
PART 2 : HANDS-ON : PROJECT AND APPLICATIONS¶
Creating a project¶
django-admin.py startproject mp_rugby_league cd mp_rugby_league
Giving the full path to the
django-admin.pyscript might be necessary on some OS. E.g. Windows
- overview of the generated files
python manage.py runserver
- settings.py
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 'NAME': 'mp_rugby_league.db', # Or path to database file if using sqlite3. 'USER': '', # Not used with sqlite3. 'PASSWORD': '', # Not used with sqlite3. 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 'PORT': '', # Set to empty string for default. Not used with sqlite3. } }
Creating an application¶
python manage.py startapp teams
- overview of the generated files
- teams/models.py
- documentation :
https://docs.djangoproject.com/en/1.4/topics/db/models/
https://docs.djangoproject.com/en/1.4/ref/models/fields/ - yeah! let's code!
- Team.name
- Player.name
from django.db import models class Team(models.Model): pass # code fields here class Player(models.Model): pass # code fields here
- documentation :
- settings.py
INSTALLED_APPS = ( # ... 'teams', )
South¶
- settings.py
INSTALLED_APPS = ( # ... 'south', )
- creating migration for a new app
python manage.py schemamigration teams --initial
- creating migration for an existing app (not the case here)
python manage.py schemamigration --auto
- creating migration for an existing app (not the case here)
- creating south's tables
python manage.py syncdb
- applying migrations
python manage.py migrate teams
Backend : managing data in the admin¶
- urls.py
activate admin : uncomment# ... from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # ... url(r'^admin/', include(admin.site.urls)), )
- settings.py
INSTALLED_APPS = ( # ... 'django.contrib.admin', # ... )
- creating admin's tables
python manage.py syncdb
- teams/admin.py
register the models
see tutorial Part 2
https://docs.djangoproject.com/en/1.4/intro/tutorial02/from django.contrib import admin from teams.models import * admin.site.register(Team) admin.site.register(Player)
- teams/models.py
def __unicode__(self): return "" # code here the desired unicode string to be returned- Player.firstname
If south installed, create and apply migration :
python manage.py schemamigration teams --auto python manage.py migrate teamsOtherwise :
- delete mp_rugby_league.db
python manage.py syncdb
- teams/models.py
- adding a relation between Player and Team :
- Player.team
- modify database accordingly :
- south : create and apply migration
- else : delete db and syncdb
- adding a relation between Player and Team :
- add some Teams and Players (objects) in the admin
Frontend : presenting data¶
- urls.py
https://docs.djangoproject.com/en/1.4/topics/http/urls/urlpatterns = patterns('', url(r'^$', 'mp_rugby_league.views.home', name='home'), # ... )
- views.py
https://docs.djangoproject.com/en/1.4/topics/http/views/
see tutorial Part 3 (shortcut version)
https://docs.djangoproject.com/en/1.4/intro/tutorial03/from django.shortcuts import render def home(request): c = { } return render(request, 'home.html', c)
- templates
https://docs.djangoproject.com/en/1.4/topics/templates/- create a templates directory in mp_rugby_league
- settings.py
import os # ... TEMPLATE_DIRS = ( os.path.join(os.path.dirname(__file__), "templates"), ) - templates/home.html
- views.py
passing a variable to the template
- templates/home.html
using a variable in the template :{{ var }}
- views.py
place to code the logic, in Python...
... easier if you explore interactively what you can code.python manage.py shell
- ORM (API) : object relation mapping
from teams.models import * teams = Team.objects.all() for t in teams: print t t = teams[0] t.player_set.all() p = Player.objects.get(id=1) p.id p = Player.objects.get(id=314) t.id players = Player.objects.filter(team__name__startswith='Pyth')
- teams/models.py
related_name = "players"
- restart the shell
t.players.all() t.players.count()
- views.py
passing the relevant variables for the home page
after playing with the ORM in the shell.
- templates/home.html
for loop in templates :{% for t in teams %} {% endfor %}
PART 3 : PIMPED MPRL PROJECT¶
Template inheritance¶
- base.html
{% block main %} {% endblock %}
- templates
{% extends "base.html" %} {% block main %} {% endblock %}
URL with parameters¶
- detail pages : receiving the object's id
- urls.py : import of teams app's urls
urlpatterns = patterns('', # ... url(r'^', include('teams.urls')), )
- urls.py : import of teams app's urls
- teams/urls.py
urlpatterns = patterns('teams.views', url(r'^teams/(?P<id>\d+)$', 'team_detail', name="team"), )
- teams/views.py
from django.shortcuts import render from teams.models import Team def team_detail(request, id): team = Team.objects.get(id=id) c = { 'team': team, } return render(request, "teams/team_detail.html", c)
- templates/teams/team_detail.html
{{ team.name }}
Pimped Admin : ModelAdmin¶
https://docs.djangoproject.com/en/1.4/ref/contrib/admin/
- teams/admin.py
- classes TeamAdmin, PlayerAdmin
inherit of ModelAdminclass TeamAdmin(admin.ModelAdmin): pass class PlayerAdmin(admin.ModelAdmin): pass
- register Model with ModelAdmin
admin.site.register(Team, TeamAdmin) admin.site.register(Player, PlayerAdmin)
- config ModelAdmin
list_display search_fields list_filter
- more?
https://docs.djangoproject.com/en/1.4/ref/contrib/admin/- fields
- fieldsets
- ...
Jump in time : download source¶
- Download the sources of the pimped project
- Extract
- Pimped? What's new?
Static files : CSS, images and js¶
https://docs.djangoproject.com/en/1.4/howto/static-files/
- directory : static
- css
- images
- js
- settings.py
PROJECT_ROOT = os.path.dirname(__file__) SITE_ROOT = os.path.dirname(PROJECT_ROOT) MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media') MEDIA_URL = '/media/' STATIC_ROOT = os.path.join(SITE_ROOT, 'site_static') STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(PROJECT_ROOT, 'static'), )
- urls.py
from django.contrib.staticfiles.urls import staticfiles_urlpatterns # ... urlpatterns += staticfiles_urlpatterns()
- templates
{{ STATIC_URL }}
Pimped templates¶
- templates/base.html
User connexion¶
- templates
- connexion.html
- deconnexion.html
- urls.py
urlpatterns = patterns('', # ... url(r'^login/$', 'django.contrib.auth.views.login', dict(template_name='connexion.html',), 'connexion' ), url(r'^logout/$', 'django.contrib.auth.views.logout', dict(template_name='deconnexion.html',), 'deconnexion' ), # ... )
- settings.py
LOGIN_URL = "/login/" LOGIN_REDIRECT_URL = "/"
PART 4 : HANDS-ON : CREATING THE SEASON APP FOR THE MPRL PROJECT¶
Create a season app¶
Add a Match model in this new app¶
- Match
- date
- place
- team1
- team2
- score1
- score2
Other exercise : age of a player¶
- Player.birth_date
- Player.age()
add a age() method on the Player class using the birth date.
CONCLUSION : CONTINUING ON¶
- Other aspects not covered here (some of them)
- permissions and decorators
- manage.py inspectdb
https://docs.djangoproject.com/en/1.4/howto/legacy-databases/ - fixtures : initial and test data
https://docs.djangoproject.com/en/1.4/howto/initial-data/ - manage.py test
- forms
- generic views
- templates : tags, filtres
- Mailing list Django users :
http://groups.google.com/group/django-users
- Channel IRC #django :
irc://irc.freenode.net/django
- Contribs, plugins
https://docs.djangoproject.com/en/dev/ref/contrib/- south
- reversion
- Other : pypi
http://pypi.python.org/
- Enjoy!