mirror of https://github.com/django/django.git
More doc improvments: moved overview into doc system so it can be distributed with the package, and fixed a few spelling errors in templates doc (fixes #31).
git-svn-id: http://code.djangoproject.com/svn/django/trunk@49 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
f7d619e4b9
commit
0f40f3b757
|
@ -0,0 +1,308 @@
|
||||||
|
===============
|
||||||
|
Django overview
|
||||||
|
===============
|
||||||
|
|
||||||
|
Because Django was developed in a fast-paced newsroom environment, it was
|
||||||
|
designed to make common Web-development tasks fast and easy. Here's an informal
|
||||||
|
overview of how to write a database-driven Web app with Django.
|
||||||
|
|
||||||
|
The goal of this document is to give you enough technical specifics to
|
||||||
|
understand how Django works, but this isn't intended to be a tutorial or
|
||||||
|
reference. Please see our more-detailed Django documentation_ when you're ready
|
||||||
|
to start a project.
|
||||||
|
|
||||||
|
.. _documentation: http://www.djangoproject.com/documentation/
|
||||||
|
|
||||||
|
Design your model
|
||||||
|
=================
|
||||||
|
|
||||||
|
Start by describing your database layout in Python code. Django's data-model API
|
||||||
|
offers many rich ways of representing your models — so far, it's been
|
||||||
|
solving two years' worth of database-schema problems. Here's a quick example::
|
||||||
|
|
||||||
|
class Reporter(meta.Model):
|
||||||
|
fields = (
|
||||||
|
meta.CharField('full_name', "reporter's full name", maxlength=70),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.full_name
|
||||||
|
|
||||||
|
class Article(meta.Model):
|
||||||
|
fields = (
|
||||||
|
meta.DateTimeField('pub_date', 'publication date'),
|
||||||
|
meta.CharField('headline', 'headline', maxlength=200),
|
||||||
|
meta.TextField('article', 'article'),
|
||||||
|
meta.ForeignKey(Reporter),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.headline
|
||||||
|
|
||||||
|
Install it
|
||||||
|
==========
|
||||||
|
|
||||||
|
Next, run the Django command-line utility. It'll create the database tables for
|
||||||
|
you automatically, in the database specified in your Django settings. Django
|
||||||
|
works with PostgreSQL and MySQL, although other database adapters are on the
|
||||||
|
way::
|
||||||
|
|
||||||
|
django-admin.py install news
|
||||||
|
|
||||||
|
Enjoy the free API
|
||||||
|
==================
|
||||||
|
|
||||||
|
With that, you've got a free, and rich, Python API to access your data. The API
|
||||||
|
is created on the fly: No code generation necessary::
|
||||||
|
|
||||||
|
# Modules are dynamically created within django.models.
|
||||||
|
# Their names are plural versions of the model class names.
|
||||||
|
>>> from django.models.news import reporters, articles
|
||||||
|
|
||||||
|
# No reporters are in the system yet.
|
||||||
|
>>> reporters.get_list()
|
||||||
|
[]
|
||||||
|
|
||||||
|
# Create a new Reporter.
|
||||||
|
>>> r = reporters.Reporter(id=None, full_name='John Smith')
|
||||||
|
|
||||||
|
# Save the object into the database. You have to call save() explicitly.
|
||||||
|
>>> r.save()
|
||||||
|
|
||||||
|
# Now it has an ID.
|
||||||
|
>>> r.id
|
||||||
|
1
|
||||||
|
|
||||||
|
# Now the new reporter is in the database.
|
||||||
|
>>> reporters.get_list()
|
||||||
|
[John Smith]
|
||||||
|
|
||||||
|
# Fields are represented as attributes on the Python object.
|
||||||
|
>>> r.full_name
|
||||||
|
'John Smith'
|
||||||
|
|
||||||
|
# Django provides a rich database lookup API that's entirely driven by keyword arguments.
|
||||||
|
>>> reporters.get_object(id__exact=1)
|
||||||
|
John Smith
|
||||||
|
>>> reporters.get_object(full_name__startswith='John')
|
||||||
|
John Smith
|
||||||
|
>>> reporters.get_object(full_name__contains='mith')
|
||||||
|
John Smith
|
||||||
|
>>> reporters.get_object(id__exact=2)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
django.models.polls.ReporterDoesNotExist: Reporter does not exist for {'id__exact': 2}
|
||||||
|
|
||||||
|
# Create an article.
|
||||||
|
>>> from datetime import datetime
|
||||||
|
>>> a = articles.Article(id=None, pub_date=datetime.now(), headline='Django is cool', article='Yeah.', reporter_id=1)
|
||||||
|
>>> a.save()
|
||||||
|
|
||||||
|
# Now the article is in the database.
|
||||||
|
>>> articles.get_list()
|
||||||
|
[Django is cool]
|
||||||
|
|
||||||
|
# Article objects get API access to related Reporter objects.
|
||||||
|
>>> r = a.get_reporter()
|
||||||
|
>>> r.full_name
|
||||||
|
'John Smith'
|
||||||
|
|
||||||
|
# And vice versa: Reporter objects get API access to Article objects.
|
||||||
|
>>> r.get_article_list()
|
||||||
|
[Django is cool]
|
||||||
|
|
||||||
|
# The API follows relationships as far as you need.
|
||||||
|
# Find all articles by a reporter whose name starts with "John".
|
||||||
|
>>> articles.get_list(reporter__full_name__startswith="John")
|
||||||
|
[Django is cool]
|
||||||
|
|
||||||
|
# Change an object by altering its attributes and calling save().
|
||||||
|
>>> r.full_name = 'Billy Goat'
|
||||||
|
>>> r.save()
|
||||||
|
|
||||||
|
# Delete an object with delete().
|
||||||
|
>>> r.delete()
|
||||||
|
|
||||||
|
A dynamic admin interface: It's not just scaffolding -- it's the whole house
|
||||||
|
============================================================================
|
||||||
|
|
||||||
|
Once your models are defined, Django can automatically create an administrative
|
||||||
|
interface — a Web site that lets authenticated users add, change and
|
||||||
|
delete objects. It's as easy as adding an extra admin attribute to your model
|
||||||
|
classes::
|
||||||
|
|
||||||
|
class Article(meta.Model):
|
||||||
|
fields = (
|
||||||
|
meta.DateTimeField('pub_date', 'publication date'),
|
||||||
|
meta.CharField('headline', 'headline', maxlength=200),
|
||||||
|
meta.TextField('article', 'article'),
|
||||||
|
meta.ForeignKey(Reporter),
|
||||||
|
)
|
||||||
|
admin = meta.Admin(
|
||||||
|
fields = (
|
||||||
|
(None, {'fields': ('headline', 'article')}),
|
||||||
|
('Extra stuff', {'fields': ('pub_date', 'reporter_id')}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
The ``admin.fields`` defines the layout of your admin form. Each element in the
|
||||||
|
fields tuple corresponds to a ``<fieldset>`` in the form.
|
||||||
|
|
||||||
|
The philosophy here is that your site is edited by a staff, or a client, or
|
||||||
|
maybe just you -- and you don't want to have to deal with creating backend
|
||||||
|
interfaces just to manage content.
|
||||||
|
|
||||||
|
Our typical workflow at World Online is to create models and get the admin sites
|
||||||
|
up and running as fast as possible, so our staff journalists can start
|
||||||
|
populating data. Then we develop the way data is presented to the public.
|
||||||
|
|
||||||
|
Design your URLs
|
||||||
|
|
||||||
|
A clean, elegant URL scheme is an important detail in a high-quality Web
|
||||||
|
application. Django lets you design URLs however you want, with no framework
|
||||||
|
limitations.
|
||||||
|
|
||||||
|
To design URLs for an app, you create a Python module. For the above
|
||||||
|
Reporter/Article example, here's what that might look like::
|
||||||
|
|
||||||
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^/articles/(?P\d{4})/$', 'myproject.news.views.articles.year_archive'),
|
||||||
|
(r'^/articles/(?P\d{4})/(?P\d{2})/$', 'myproject.news.views.articles.month_archive'),
|
||||||
|
(r'^/articles/(?P\d{4})/(?P\d{2})/$', 'myproject.news.views.articles.month_archive'),
|
||||||
|
(r'^/articles/(?P\d{4})/(?P\d{2})/(?P\d+)/$', 'myproject.news.views.articles.article_detail'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
The code above maps URLs, as regular expressions, to the location of Python
|
||||||
|
callback functions (views). The regular expressions use parenthesis to "capture"
|
||||||
|
values from the URLs. When a user requests a page, Django runs through each
|
||||||
|
regular expression, in order, and stops at the first one that matches the
|
||||||
|
requested URL. (If none of them matches, Django calls a special 404 view.) This
|
||||||
|
is blazingly fast, because the regular expressions are compiled at load time.
|
||||||
|
|
||||||
|
Once one of the regexes matches, Django imports and calls the given view, which
|
||||||
|
is a simple Python function. Each view gets passed a request object —
|
||||||
|
which contains request metadata and lets you access GET and POST data as simple
|
||||||
|
dictionaries — and the values captured in the regex, via keyword
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
For example, if a user requested the URL "/articles/2005/05/39323/", Django
|
||||||
|
would call the function ``myproject.news.views.articles.article_detail(request,
|
||||||
|
year='2005', month='05', article_id='39323')``.
|
||||||
|
|
||||||
|
Write your views
|
||||||
|
================
|
||||||
|
|
||||||
|
Each view is responsible for doing one of two things: Returning an
|
||||||
|
``HttpResponse`` object containing the content for the requested page, or
|
||||||
|
raising an exception such as ``Http404``. The rest is up to you.
|
||||||
|
|
||||||
|
Generally, a view retrieves data according to the parameters, loads a template
|
||||||
|
and renders the template with the retrieved data. Here's an example view for
|
||||||
|
article_detail from above::
|
||||||
|
|
||||||
|
from django.models.news import articles
|
||||||
|
|
||||||
|
def article_detail(request, year, month, article_id):
|
||||||
|
# Use the Django API to find an object matching the URL criteria.
|
||||||
|
try:
|
||||||
|
a = articles.get_object(pub_date__year=year, pub_date__month=month, id__exact=article_id)
|
||||||
|
except articles.ArticleDoesNotExist:
|
||||||
|
raise Http404
|
||||||
|
t = template_loader.get_template('news/article_detail')
|
||||||
|
c = Context(request, {
|
||||||
|
'article': a,
|
||||||
|
})
|
||||||
|
content = t.render(c)
|
||||||
|
return HttpResponse(content)
|
||||||
|
|
||||||
|
This example uses Django's template system, which has several key features.
|
||||||
|
|
||||||
|
Design your templates
|
||||||
|
=====================
|
||||||
|
|
||||||
|
The code above loads the ``news/article_detail`` template.
|
||||||
|
|
||||||
|
Django has a template search path, which allows you to minimize redundancy among
|
||||||
|
templates. In your Django settings, you specify a list of directories to check
|
||||||
|
for templates. If a template doesn't exist in the first directory, it checks the
|
||||||
|
second, and so on.
|
||||||
|
|
||||||
|
Let's say the ``news/article_detail`` template was found. Here's what that might
|
||||||
|
look like::
|
||||||
|
|
||||||
|
{% extends "base" %}
|
||||||
|
|
||||||
|
{% block title %}{{ article.headline }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{{ article.headline }}</h1>
|
||||||
|
<p>By {{ article.get_reporter.full_name }}</p>
|
||||||
|
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
|
||||||
|
{{ article.article }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
It should look straightforward. Variables are surrounded by double-curly braces.
|
||||||
|
``{{ article.headline }}`` means "Output the value of the article's headline
|
||||||
|
attribute." But dots aren't used only for attribute lookup: They also can do
|
||||||
|
dictionary-key lookup, index lookup and function calls (as is the case with
|
||||||
|
``article.get_reporter``).
|
||||||
|
|
||||||
|
Note ``{{ article.pub_date|date:"F j, Y" }}`` uses a Unix-style "pipe" (the "|"
|
||||||
|
character). This is called a template filter, and it's a way to filter the value
|
||||||
|
of a variable. In this case, the date filter formats a Python datetime object in
|
||||||
|
the given format (as found in PHP's date function; yes, there is one good idea
|
||||||
|
in PHP).
|
||||||
|
|
||||||
|
You can chain together as many filters as you'd like. You can write custom
|
||||||
|
filters. You can write custom template tags, which run custom Python code behind
|
||||||
|
the scenes.
|
||||||
|
|
||||||
|
Finally, Django uses the concept of template inheritance: That's what the ``{%
|
||||||
|
extends "base" %}`` does. It means "First load the template called 'base', which
|
||||||
|
has defined a bunch of blocks, and fill the blocks with the following blocks."
|
||||||
|
In short, that lets you dramatically cut down on redundancy in templates: Each
|
||||||
|
template has to define only what's unique to that template.
|
||||||
|
|
||||||
|
Here's what the "base" template might look like::
|
||||||
|
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{% block title %}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="sitelogo.gif" alt="Logo" />
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
Simplistically, it defines the look-and-feel of the site (with the site's logo),
|
||||||
|
and provides "holes" for child templates to fill. This makes a site redesign as
|
||||||
|
easy as changing a single file — the base template.
|
||||||
|
|
||||||
|
Note that you don't have to use Django's template system if you prefer another
|
||||||
|
system. While Django's template system is particularly well-integrated with
|
||||||
|
Django's model layer, nothing forces you to use it. For that matter, you don't
|
||||||
|
have to use Django's API, either. You can use another database abstraction
|
||||||
|
layer, you can read XML files, you can read files off disk, or anything you
|
||||||
|
want. Each piece of Django — models, views, templates — is decoupled
|
||||||
|
from the next.
|
||||||
|
|
||||||
|
This is just the surface
|
||||||
|
========================
|
||||||
|
|
||||||
|
This has been only a quick overview of Django's functionality. Some more useful
|
||||||
|
features:
|
||||||
|
|
||||||
|
* A caching framework that integrates with memcached or other backends.
|
||||||
|
* An RSS framework that makes creating RSS feeds as easy as writing a
|
||||||
|
small Python class.
|
||||||
|
* More sexy automatically-generated admin features — this overview barely
|
||||||
|
scratched the surface
|
||||||
|
|
||||||
|
The next obvious steps are for you to download Django, read the documentation
|
||||||
|
and join the community. Thanks for your interest!
|
|
@ -21,7 +21,8 @@ To actually be useful, a template will contain **variables**, which get replaced
|
||||||
with values from the database when the template is evaluated, and **tags**,
|
with values from the database when the template is evaluated, and **tags**,
|
||||||
which control the logic of the template.
|
which control the logic of the template.
|
||||||
|
|
||||||
Below is a minimal template that I'll be using to illustrate the parts of a template throughout this introduction::
|
Below is a minimal template that I'll be using to illustrate the parts of a
|
||||||
|
template throughout this introduction::
|
||||||
|
|
||||||
{% extends base_generic %}
|
{% extends base_generic %}
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ Variables look like this: ``{{ variable }}``. When the template engine
|
||||||
encounters a variable, it evaluates that variable and replaces the variable with
|
encounters a variable, it evaluates that variable and replaces the variable with
|
||||||
the result. Many variables will be structures with named attributes; you can
|
the result. Many variables will be structures with named attributes; you can
|
||||||
"drill down" into these structures with dots (``.``), so in the above example ``
|
"drill down" into these structures with dots (``.``), so in the above example ``
|
||||||
{{ section.title }}`` will be replaces with the ``title`` attribute of the
|
{{ section.title }}`` will be replaced with the ``title`` attribute of the
|
||||||
``section`` object.
|
``section`` object.
|
||||||
|
|
||||||
If you use a variable that doesn't exist, it will be silently ignored; the
|
If you use a variable that doesn't exist, it will be silently ignored; the
|
||||||
|
@ -61,7 +62,7 @@ Variables may be modified before being displayed by **filters**.
|
||||||
What's a filter?
|
What's a filter?
|
||||||
================
|
================
|
||||||
|
|
||||||
Filters look like this: ``{{ name|lower }}``. This display the value of the
|
Filters look like this: ``{{ name|lower }}``. This displays the value of the
|
||||||
``{{ name }}`` variable after being filtered through the ``lower`` filter which,
|
``{{ name }}`` variable after being filtered through the ``lower`` filter which,
|
||||||
as you might have guessed, lowercases the text passed through it.
|
as you might have guessed, lowercases the text passed through it.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue