The django official tutorial consists of 4 parts, unnecessarily long, mixes commands with text, and omit some important details. Here is an attempt at providing a more complete and more condensed version of the tutorial.
- Install Django. The latest tutorial uses a newer version of Django that is not backward compatible. Therefore, it is best to install Django from svn:
svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk cd django-trunk sudo python setup.py install
- Create a Project. Create a new project under the current directory called mysite:
django-admin.py startproject mysite
- Configure Database. For this example, we will use an sqlite3 database.
mkdir db chmod a+rwx db chmod g+s db
The Web server needs access and write permission. The g+s ensures that group ownership of created files in db remains the same that of db. Edit mysite/settings.py as follows:
DATABASE_ENGINE = 'sqlite3' DATABASE_NAME = '/path/to/mysite/db/mysite.db'
Create the database and the tables:
python manage.py syncdb
- Create a Polls Application. From the mysite directory, run the command:
python manage.py startapp polls
- Create the Polls Data Model. Edit the file mysite/polls/models.py as follows:
from django.db import models class Poll(models.Model): question = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') def __unicode__(self): return self.question class Choice(models.Model): poll = models.ForeignKey(Poll) choice = models.CharField(max_length=200) votes = models.IntegerField() def __unicode__(self): return self.choice
And synchronize the database:
python manage.py syncdb
- Enable the Admin Interface Enable the admin application in mysite/settings.py:
INSTALLED_APPS = ( .... "django.contrib.admin", ....
Then enable the admin URLs in mysite/urls.py:
from django.conf.urls.defaults import * from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', (r'^admin/', include(admin.site.urls)), )
And synchronize the database:
python manage.py syncdb
Note that at this point we only enabled the admin URL. The home page will no longer work until we add another pattern to match it.
- Test the admin Interface. Either configure your Web server according to the docs, or use the development built-in server from the mysite direcotry:
python manage.py runserver 0.0.0.0:8080
Visit the admin interface from a Web browser at:
http://127.0.0.1:8080/admin
- Enable admin in Polls. Create a file mysite/polls/admin.py with:
from mysite.polls.models import Poll from django.contrib import admin admin.site.register(Poll)
You should now see the Polls in the admin interface.
Note: don’t forget to restart the Web server every time you make changes to your python code.
- Customize the Polls Admin. Edit mysite/polls/admin.py to be:
from mysite.polls.models import Poll from mysite.polls.models import 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']}), ] inlines = [ChoiceInline] list_display = ('question', 'pub_date', 'was_published_today') list_filter = ['pub_date'] search_fields = ['question'] date_hierarchy = 'pub_date' admin.site.register(Poll, PollAdmin)
Each line adds a new functionality to the admin interface, and the functions are independent of each other. Most should self-evident. Feel free to experiment.
To customize the how the “was_published_today” header is displayed, change mysite/polls/model.py to:
def was_published_today(self): return self.pub_date.date() == datetime.date.today() was_published_today.short_description = 'Published today?'
- Setup URLs. Create the polls urls in mysite/polls/urls.py:
from django.conf.urls.defaults import * urlpatterns = patterns('mysite.polls.views', (r'^$', 'index'), (r'^(?P<poll_id>\d+)/$', 'detail'), (r'^(?P<poll_id>\d+)/results/$', 'results'), (r'^(?P<poll_id>\d+)/vote/$', 'vote'), )
Add polls to the site urls in mysite/urls.py by including the pattern:
(r'^polls/', include('mysite.polls.urls')),
- Setup a Templates Directory.Create a directory mysite/templates. Update mysite/setting.py to use this direcotyr:
TEMPLATE_DIRS = ( '/path/to/mysite/templates', )
- Create the Index View and Templates. Create a file mysite/polls/views.py:
from django.shortcuts import render_to_response, get_object_or_404 from mysite.polls.models import Poll def index(request): latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5] return render_to_response('polls/index.html', {'latest_poll_list': latest_poll_list})
And the index template mysite/templates/polls/index.html:
{% if latest_poll_list %} <ul> {% for poll in latest_poll_list %} <li>{{ poll.question }}</li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}
- Create the Detail View and Template. Add to mysite/polls/views.py:
def detail(request, poll_id): p = get_object_or_404(Poll, pk=poll_id) return render_to_response('polls/detail.html', {'poll': p})
And create the template mysite/templates/detail.html:
<h1>{{ poll.question }}</h1> {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} <form action="/polls/{{ poll.id }}/vote/" method="post"> {% for choice in poll.choice_set.all %} <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /> <label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br /> {% endfor %} <input type="submit" value="Vote" /> </form>
- Create the Vote Handler. Edit mysite/polls/views.py to include:
from django.shortcuts import get_object_or_404, render_to_response from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse from mysite.polls.models import Choice, Poll # ... def vote(request, poll_id): p = get_object_or_404(Poll, pk=poll_id) try: selected_choice = p.choice_set.get(pk=request.POST['choice']) except (KeyError, Choice.DoesNotExist): # Redisplay the poll voting form. return render_to_response('polls/detail.html', { 'poll': p, 'error_message': "You didn't select a choice.", }) else: selected_choice.votes += 1 selected_choice.save() # Always return an HttpResponseRedirect after successfully dealing # with POST data. This prevents data from being posted twice if a # user hits the Back button. return HttpResponseRedirect(reverse('mysite.polls.views.results', args=(p.id,)))
- Create the Results View and Template. Edit mysite/polls/views.py to include the results view:
def results(request, poll_id): p = get_object_or_404(Poll, pk=poll_id) return render_to_response('polls/results.html', {'poll': p})
Create a results templates file mysite/templates/polls/results.html with:
<h1>{{ poll.question }}</h1> <ul> {% for choice in poll.choice_set.all %} <li>{{ choice.choice }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li> {% endfor %} </ul>
Et Voilà! These steps cover most of the 4-part tutorial, excluding templating the admin area and using the generic views. For completeness, I include a sample apache config file that uses virtual hosts so you can go through this tutorial with apache.
<VirtualHost *> ServerAdmin webmaster@localhost ServerName django-tutorial.osrd.org DocumentRoot /path/to/django-projects/mysite <Directory /path/to/django-projects/mysite > Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> ErrorLog /var/log/apache2/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog /var/log/apache2/access.log combined ServerSignature On <LocationMatch "/mysite/*"> SetHandler mod_python PythonHandler django.core.handlers.modpython SetEnv DJANGO_SETTINGS_MODULE mysite.settings PythonOption django.root /mysite PythonDebug On PythonPath "['/path/to/django-projects'] + sys.path" </LocationMatch> <Location "/media"> SetHandler None </Location> <LocationMatch "\.(jpg|gif|png)$"> SetHandler None </LocationMatch> </VirtualHost>
If you find any omissions or inaccuracies, please report them privately or in the comments and I’ll update the tutorial accordingly.
You have made a wonderful summary of the official tutorial. Its Ideal to refresh the memory and quickly explain to new djangonauts why Django Rocks 🙂
You have made a wonderful summary of the official tutorial. Its Ideal to refresh the memory and quickly explain to new djangonauts why Django Rocks 🙂
PS:
you need to syncdb before step.7. After adding “django.contrib.admin”,
the table django_admin_log must be created.
Thanks Lerina. I updated the tutorial accordingly.
Great revision! Here’s a couple comments.
Step 5 : Should read mysite/polls/models.py not model.py
Step 6: FYI, url admin in 1.0.2 is:
(r’^admin/(.*)’, admin.site.root)
Step 7: This may be easier for people that need to change it:
alternate: python manage.py runserver 0.0.0.0:80
Step 13: Incorrect URL, line should read:
Thanks!!
oops, it dropped my html looking correction…
in Step 13, the “form” line from the code should not contain “/mysite”
I appropriate your effort to posted a django official tutorial. This tutorial is impressive because of the detail review.
Web Design Quote
Nice info so for,,,
Thanks for the feedback George.
The include method in step 6 is the recommended approach and using admin.site.root is depricated as of django 1.1. See Features deprecated in 1.1.
I incorporate the other corrections. Thanks again.
I agree with your assessment of the Django official tutorial. Thanks for sharing your condensed/summary/ version.
Thanks for this blog. I am new at development and this will be a big help.
thanks for taking the time to do this its useful.
for a real beginner i think too much to take in, but useful in conjunction with the full tutorial.
mark
hi, how can i call the database in django views.py ?
from django.conf.urls.defaults import *
has been replaced with:
from django.conf.urls import patterns, url, include
In Django 1.6 and above.