From 65411d01d448ff0cd4abd14eee14cf60b5f8fc20 Mon Sep 17 00:00:00 2001 From: Nishanth Amuluru Date: Sat, 8 Jan 2011 11:20:57 +0530 Subject: Added buildout stuff and made changes accordingly --HG-- rename : profile/management/__init__.py => eggs/djangorecipe-0.20-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/djangorecipe-0.20-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/infrae.subversion-1.4.5-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/infrae.subversion-1.4.5-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/py-1.4.0-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/py-1.4.0-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/zc.buildout-1.5.2-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/zc.buildout-1.5.2-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/zc.recipe.egg-1.3.2-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/zc.recipe.egg-1.3.2-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => parts/django/Django.egg-info/dependency_links.txt rename : taskapp/models.py => parts/django/django/conf/app_template/models.py rename : taskapp/tests.py => parts/django/django/conf/app_template/tests.py rename : taskapp/views.py => parts/django/django/conf/app_template/views.py rename : taskapp/views.py => parts/django/django/contrib/gis/tests/geo3d/views.py rename : profile/management/__init__.py => parts/django/tests/modeltests/delete/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/files/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/invalid_models/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/m2m_signals/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/model_package/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/management/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/management/commands/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/models.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/delete_regress/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/file_storage/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/max_lengths/__init__.py rename : profile/forms.py => pytask/profile/forms.py rename : profile/management/__init__.py => pytask/profile/management/__init__.py rename : profile/management/commands/seed_db.py => pytask/profile/management/commands/seed_db.py rename : profile/models.py => pytask/profile/models.py rename : profile/templatetags/user_tags.py => pytask/profile/templatetags/user_tags.py rename : taskapp/tests.py => pytask/profile/tests.py rename : profile/urls.py => pytask/profile/urls.py rename : profile/utils.py => pytask/profile/utils.py rename : profile/views.py => pytask/profile/views.py rename : static/css/base.css => pytask/static/css/base.css rename : taskapp/tests.py => pytask/taskapp/tests.py rename : taskapp/views.py => pytask/taskapp/views.py rename : templates/base.html => pytask/templates/base.html rename : templates/profile/browse_notifications.html => pytask/templates/profile/browse_notifications.html rename : templates/profile/edit.html => pytask/templates/profile/edit.html rename : templates/profile/view.html => pytask/templates/profile/view.html rename : templates/profile/view_notification.html => pytask/templates/profile/view_notification.html rename : templates/registration/activate.html => pytask/templates/registration/activate.html rename : templates/registration/activation_email.txt => pytask/templates/registration/activation_email.txt rename : templates/registration/activation_email_subject.txt => pytask/templates/registration/activation_email_subject.txt rename : templates/registration/logged_out.html => pytask/templates/registration/logged_out.html rename : templates/registration/login.html => pytask/templates/registration/login.html rename : templates/registration/logout.html => pytask/templates/registration/logout.html rename : templates/registration/password_change_done.html => pytask/templates/registration/password_change_done.html rename : templates/registration/password_change_form.html => pytask/templates/registration/password_change_form.html rename : templates/registration/password_reset_complete.html => pytask/templates/registration/password_reset_complete.html rename : templates/registration/password_reset_confirm.html => pytask/templates/registration/password_reset_confirm.html rename : templates/registration/password_reset_done.html => pytask/templates/registration/password_reset_done.html rename : templates/registration/password_reset_email.html => pytask/templates/registration/password_reset_email.html rename : templates/registration/password_reset_form.html => pytask/templates/registration/password_reset_form.html rename : templates/registration/registration_complete.html => pytask/templates/registration/registration_complete.html rename : templates/registration/registration_form.html => pytask/templates/registration/registration_form.html rename : utils.py => pytask/utils.py --- parts/django/docs/intro/_images/admin01.png | Bin 0 -> 18233 bytes parts/django/docs/intro/_images/admin02.png | Bin 0 -> 64260 bytes parts/django/docs/intro/_images/admin02t.png | Bin 0 -> 24726 bytes parts/django/docs/intro/_images/admin03.png | Bin 0 -> 75434 bytes parts/django/docs/intro/_images/admin03t.png | Bin 0 -> 28131 bytes parts/django/docs/intro/_images/admin04.png | Bin 0 -> 57718 bytes parts/django/docs/intro/_images/admin04t.png | Bin 0 -> 22806 bytes parts/django/docs/intro/_images/admin05.png | Bin 0 -> 28875 bytes parts/django/docs/intro/_images/admin05t.png | Bin 0 -> 22754 bytes parts/django/docs/intro/_images/admin06.png | Bin 0 -> 22780 bytes parts/django/docs/intro/_images/admin06t.png | Bin 0 -> 18156 bytes parts/django/docs/intro/_images/admin07.png | Bin 0 -> 19804 bytes parts/django/docs/intro/_images/admin08.png | Bin 0 -> 31552 bytes parts/django/docs/intro/_images/admin08t.png | Bin 0 -> 23883 bytes parts/django/docs/intro/_images/admin09.png | Bin 0 -> 16318 bytes parts/django/docs/intro/_images/admin10.png | Bin 0 -> 10914 bytes parts/django/docs/intro/_images/admin11.png | Bin 0 -> 33563 bytes parts/django/docs/intro/_images/admin11t.png | Bin 0 -> 26365 bytes parts/django/docs/intro/_images/admin12.png | Bin 0 -> 12682 bytes parts/django/docs/intro/_images/admin13.png | Bin 0 -> 22062 bytes parts/django/docs/intro/_images/admin13t.png | Bin 0 -> 18690 bytes parts/django/docs/intro/_images/admin14.png | Bin 0 -> 28987 bytes parts/django/docs/intro/_images/admin14t.png | Bin 0 -> 23460 bytes parts/django/docs/intro/index.txt | 36 ++ parts/django/docs/intro/install.txt | 84 ++++ parts/django/docs/intro/overview.txt | 324 +++++++++++++ parts/django/docs/intro/tutorial01.txt | 690 +++++++++++++++++++++++++++ parts/django/docs/intro/tutorial02.txt | 465 ++++++++++++++++++ parts/django/docs/intro/tutorial03.txt | 546 +++++++++++++++++++++ parts/django/docs/intro/tutorial04.txt | 346 ++++++++++++++ parts/django/docs/intro/whatsnext.txt | 231 +++++++++ 31 files changed, 2722 insertions(+) create mode 100644 parts/django/docs/intro/_images/admin01.png create mode 100644 parts/django/docs/intro/_images/admin02.png create mode 100644 parts/django/docs/intro/_images/admin02t.png create mode 100644 parts/django/docs/intro/_images/admin03.png create mode 100644 parts/django/docs/intro/_images/admin03t.png create mode 100644 parts/django/docs/intro/_images/admin04.png create mode 100644 parts/django/docs/intro/_images/admin04t.png create mode 100644 parts/django/docs/intro/_images/admin05.png create mode 100644 parts/django/docs/intro/_images/admin05t.png create mode 100644 parts/django/docs/intro/_images/admin06.png create mode 100644 parts/django/docs/intro/_images/admin06t.png create mode 100644 parts/django/docs/intro/_images/admin07.png create mode 100644 parts/django/docs/intro/_images/admin08.png create mode 100644 parts/django/docs/intro/_images/admin08t.png create mode 100644 parts/django/docs/intro/_images/admin09.png create mode 100644 parts/django/docs/intro/_images/admin10.png create mode 100644 parts/django/docs/intro/_images/admin11.png create mode 100644 parts/django/docs/intro/_images/admin11t.png create mode 100644 parts/django/docs/intro/_images/admin12.png create mode 100644 parts/django/docs/intro/_images/admin13.png create mode 100644 parts/django/docs/intro/_images/admin13t.png create mode 100644 parts/django/docs/intro/_images/admin14.png create mode 100644 parts/django/docs/intro/_images/admin14t.png create mode 100644 parts/django/docs/intro/index.txt create mode 100644 parts/django/docs/intro/install.txt create mode 100644 parts/django/docs/intro/overview.txt create mode 100644 parts/django/docs/intro/tutorial01.txt create mode 100644 parts/django/docs/intro/tutorial02.txt create mode 100644 parts/django/docs/intro/tutorial03.txt create mode 100644 parts/django/docs/intro/tutorial04.txt create mode 100644 parts/django/docs/intro/whatsnext.txt (limited to 'parts/django/docs/intro') diff --git a/parts/django/docs/intro/_images/admin01.png b/parts/django/docs/intro/_images/admin01.png new file mode 100644 index 0000000..28f14d6 Binary files /dev/null and b/parts/django/docs/intro/_images/admin01.png differ diff --git a/parts/django/docs/intro/_images/admin02.png b/parts/django/docs/intro/_images/admin02.png new file mode 100644 index 0000000..4b49ebb Binary files /dev/null and b/parts/django/docs/intro/_images/admin02.png differ diff --git a/parts/django/docs/intro/_images/admin02t.png b/parts/django/docs/intro/_images/admin02t.png new file mode 100644 index 0000000..d7519d1 Binary files /dev/null and b/parts/django/docs/intro/_images/admin02t.png differ diff --git a/parts/django/docs/intro/_images/admin03.png b/parts/django/docs/intro/_images/admin03.png new file mode 100644 index 0000000..635226c Binary files /dev/null and b/parts/django/docs/intro/_images/admin03.png differ diff --git a/parts/django/docs/intro/_images/admin03t.png b/parts/django/docs/intro/_images/admin03t.png new file mode 100644 index 0000000..94273cb Binary files /dev/null and b/parts/django/docs/intro/_images/admin03t.png differ diff --git a/parts/django/docs/intro/_images/admin04.png b/parts/django/docs/intro/_images/admin04.png new file mode 100644 index 0000000..982420a Binary files /dev/null and b/parts/django/docs/intro/_images/admin04.png differ diff --git a/parts/django/docs/intro/_images/admin04t.png b/parts/django/docs/intro/_images/admin04t.png new file mode 100644 index 0000000..a2ec8bb Binary files /dev/null and b/parts/django/docs/intro/_images/admin04t.png differ diff --git a/parts/django/docs/intro/_images/admin05.png b/parts/django/docs/intro/_images/admin05.png new file mode 100644 index 0000000..b424393 Binary files /dev/null and b/parts/django/docs/intro/_images/admin05.png differ diff --git a/parts/django/docs/intro/_images/admin05t.png b/parts/django/docs/intro/_images/admin05t.png new file mode 100644 index 0000000..a5da950 Binary files /dev/null and b/parts/django/docs/intro/_images/admin05t.png differ diff --git a/parts/django/docs/intro/_images/admin06.png b/parts/django/docs/intro/_images/admin06.png new file mode 100644 index 0000000..5f24d4e Binary files /dev/null and b/parts/django/docs/intro/_images/admin06.png differ diff --git a/parts/django/docs/intro/_images/admin06t.png b/parts/django/docs/intro/_images/admin06t.png new file mode 100644 index 0000000..fb65e0a Binary files /dev/null and b/parts/django/docs/intro/_images/admin06t.png differ diff --git a/parts/django/docs/intro/_images/admin07.png b/parts/django/docs/intro/_images/admin07.png new file mode 100644 index 0000000..b21022f Binary files /dev/null and b/parts/django/docs/intro/_images/admin07.png differ diff --git a/parts/django/docs/intro/_images/admin08.png b/parts/django/docs/intro/_images/admin08.png new file mode 100644 index 0000000..ddac57e Binary files /dev/null and b/parts/django/docs/intro/_images/admin08.png differ diff --git a/parts/django/docs/intro/_images/admin08t.png b/parts/django/docs/intro/_images/admin08t.png new file mode 100644 index 0000000..83773bb Binary files /dev/null and b/parts/django/docs/intro/_images/admin08t.png differ diff --git a/parts/django/docs/intro/_images/admin09.png b/parts/django/docs/intro/_images/admin09.png new file mode 100644 index 0000000..ba7de1b Binary files /dev/null and b/parts/django/docs/intro/_images/admin09.png differ diff --git a/parts/django/docs/intro/_images/admin10.png b/parts/django/docs/intro/_images/admin10.png new file mode 100644 index 0000000..07a9bf3 Binary files /dev/null and b/parts/django/docs/intro/_images/admin10.png differ diff --git a/parts/django/docs/intro/_images/admin11.png b/parts/django/docs/intro/_images/admin11.png new file mode 100644 index 0000000..6c583fd Binary files /dev/null and b/parts/django/docs/intro/_images/admin11.png differ diff --git a/parts/django/docs/intro/_images/admin11t.png b/parts/django/docs/intro/_images/admin11t.png new file mode 100644 index 0000000..af792b8 Binary files /dev/null and b/parts/django/docs/intro/_images/admin11t.png differ diff --git a/parts/django/docs/intro/_images/admin12.png b/parts/django/docs/intro/_images/admin12.png new file mode 100644 index 0000000..aac5c0d Binary files /dev/null and b/parts/django/docs/intro/_images/admin12.png differ diff --git a/parts/django/docs/intro/_images/admin13.png b/parts/django/docs/intro/_images/admin13.png new file mode 100644 index 0000000..49a5950 Binary files /dev/null and b/parts/django/docs/intro/_images/admin13.png differ diff --git a/parts/django/docs/intro/_images/admin13t.png b/parts/django/docs/intro/_images/admin13t.png new file mode 100644 index 0000000..7dc01e1 Binary files /dev/null and b/parts/django/docs/intro/_images/admin13t.png differ diff --git a/parts/django/docs/intro/_images/admin14.png b/parts/django/docs/intro/_images/admin14.png new file mode 100644 index 0000000..b1f4a54 Binary files /dev/null and b/parts/django/docs/intro/_images/admin14.png differ diff --git a/parts/django/docs/intro/_images/admin14t.png b/parts/django/docs/intro/_images/admin14t.png new file mode 100644 index 0000000..86c3acc Binary files /dev/null and b/parts/django/docs/intro/_images/admin14t.png differ diff --git a/parts/django/docs/intro/index.txt b/parts/django/docs/intro/index.txt new file mode 100644 index 0000000..bc61be7 --- /dev/null +++ b/parts/django/docs/intro/index.txt @@ -0,0 +1,36 @@ +Getting started +=============== + +New to Django? Or to Web development in general? Well, you came to the right +place: read this material to quickly get up and running. + +.. toctree:: + :maxdepth: 1 + + overview + install + tutorial01 + tutorial02 + tutorial03 + tutorial04 + whatsnext + +.. seealso:: + + If you're new to Python_, you might want to start by getting an idea of what + the language is like. Django is 100% Python, so if you've got minimal + comfort with Python you'll probably get a lot more out of Django. + + If you're new to programming entirely, you might want to start with this + `list of Python resources for non-programmers`_ + + If you already know a few other languages and want to get up to speed with + Python quickly, we recommend `Dive Into Python`_ (also available in a + `dead-tree version`_). If that's not quite your style, there are quite + a few other `books about Python`_. + + .. _python: http://python.org/ + .. _list of Python resources for non-programmers: http://wiki.python.org/moin/BeginnersGuide/NonProgrammers + .. _dive into python: http://diveintopython.org/ + .. _dead-tree version: http://www.amazon.com/exec/obidos/ASIN/1590593561/ref=nosim/jacobian20 + .. _books about Python: http://wiki.python.org/moin/PythonBooks \ No newline at end of file diff --git a/parts/django/docs/intro/install.txt b/parts/django/docs/intro/install.txt new file mode 100644 index 0000000..327686f --- /dev/null +++ b/parts/django/docs/intro/install.txt @@ -0,0 +1,84 @@ +Quick install guide +=================== + +Before you can use Django, you'll need to get it installed. We have a +:doc:`complete installation guide ` that covers all the +possibilities; this guide will guide you to a simple, minimal installation +that'll work while you walk through the introduction. + +Install Python +-------------- + +Being a Python Web framework, Django requires Python. It works with any Python +version from 2.4 to 2.7 (due to backwards +incompatibilities in Python 3.0, Django does not currently work with +Python 3.0; see :doc:`the Django FAQ ` for more +information on supported Python versions and the 3.0 transition), but we recommend installing Python 2.5 or later. If you do so, you won't need to set up a database just yet: Python 2.5 or later includes a lightweight database called SQLite_. + +.. _sqlite: http://sqlite.org/ + +Get Python at http://www.python.org. If you're running Linux or Mac OS X, you +probably already have it installed. + +.. admonition:: Django on Jython + + If you use Jython_ (a Python implementation for the Java platform), you'll + need to follow a few additional steps. See :doc:`/howto/jython` for details. + +.. _jython: http://www.jython.org/ + +You can verify that Python's installed by typing ``python`` from your shell; you should see something like:: + + Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17) + [GCC 4.0.1 (Apple Inc. build 5465)] on darwin + Type "help", "copyright", "credits" or "license" for more information. + >>> + +Set up a database +----------------- + +If you installed Python 2.5 or later, you can skip this step for now. + +If not, or if you'd like to work with a "large" database engine like PostgreSQL, +MySQL, or Oracle, consult the :ref:`database installation information +`. + +Remove any old versions of Django +--------------------------------- + +If you are upgrading your installation of Django from a previous version, you +will need to :ref:`uninstall the old Django version before installing the new +version `. + +Install Django +-------------- + +You've got three easy options to install Django: + + * Install a version of Django :doc:`provided by your operating system + distribution `. This is the quickest option for those + who have operating systems that distribute Django. + + * :ref:`Install an official release `. This + is the best approach for users who want a stable version number and aren't + concerned about running a slightly older version of Django. + + * :ref:`Install the latest development version + `. This is best for users who want the + latest-and-greatest features and aren't afraid of running brand-new code. + +.. admonition:: Always refer to the documentation that corresponds to the + version of Django you're using! + + If you do either of the first two steps, keep an eye out for parts of the + documentation marked **new in development version**. That phrase flags + features that are only available in development versions of Django, and + they likely won't work with an official release. + +That's it! +---------- + +That's it -- you can now :doc:`move onto the tutorial `. + + + diff --git a/parts/django/docs/intro/overview.txt b/parts/django/docs/intro/overview.txt new file mode 100644 index 0000000..34572a6 --- /dev/null +++ b/parts/django/docs/intro/overview.txt @@ -0,0 +1,324 @@ +================== +Django at a glance +================== + +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 -- but we've got both! When you're ready to start a project, you can +:doc:`start with the tutorial ` or :doc:`dive right into more +detailed documentation `. + +Design your model +================= + +Although you can use Django without a database, it comes with an +object-relational mapper in which you describe your database layout in Python +code. + +The :doc:`data-model syntax ` 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, which might be saved in +the file ``mysite/news/models.py``:: + + class Reporter(models.Model): + full_name = models.CharField(max_length=70) + + def __unicode__(self): + return self.full_name + + class Article(models.Model): + pub_date = models.DateTimeField() + headline = models.CharField(max_length=200) + content = models.TextField() + reporter = models.ForeignKey(Reporter) + + def __unicode__(self): + return self.headline + +Install it +========== + +Next, run the Django command-line utility to create the database tables +automatically: + +.. code-block:: bash + + manage.py syncdb + +The :djadmin:`syncdb` command looks at all your available models and creates +tables in your database for whichever tables don't already exist. + +Enjoy the free API +================== + +With that, you've got a free, and rich, :doc:`Python API ` to +access your data. The API is created on the fly, no code generation necessary:: + + # Import the models we created from our "news" app + >>> from news.models import Reporter, Article + + # No reporters are in the system yet. + >>> Reporter.objects.all() + [] + + # Create a new Reporter. + >>> r = Reporter(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. + >>> Reporter.objects.all() + [] + + # Fields are represented as attributes on the Python object. + >>> r.full_name + 'John Smith' + + # Django provides a rich database lookup API. + >>> Reporter.objects.get(id=1) + + >>> Reporter.objects.get(full_name__startswith='John') + + >>> Reporter.objects.get(full_name__contains='mith') + + >>> Reporter.objects.get(id=2) + Traceback (most recent call last): + ... + DoesNotExist: Reporter matching query does not exist. + + # Create an article. + >>> from datetime import datetime + >>> a = Article(pub_date=datetime.now(), headline='Django is cool', + ... content='Yeah.', reporter=r) + >>> a.save() + + # Now the article is in the database. + >>> Article.objects.all() + [] + + # Article objects get API access to related Reporter objects. + >>> r = a.reporter + >>> r.full_name + 'John Smith' + + # And vice versa: Reporter objects get API access to Article objects. + >>> r.article_set.all() + [] + + # The API follows relationships as far as you need, performing efficient + # JOINs for you behind the scenes. + # This finds all articles by a reporter whose name starts with "John". + >>> Article.objects.filter(reporter__full_name__startswith="John") + [] + + # 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 a professional, +production ready :doc:`administrative interface ` -- a Web +site that lets authenticated users add, change and delete objects. It's as easy +as registering your model in the admin site:: + + # In models.py... + + from django.db import models + + class Article(models.Model): + pub_date = models.DateTimeField() + headline = models.CharField(max_length=200) + content = models.TextField() + reporter = models.ForeignKey(Reporter) + + + # In admin.py in the same directory... + + import models + from django.contrib import admin + + admin.site.register(models.Article) + +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. + +One typical workflow in creating Django apps is to create models and get the +admin sites up and running as fast as possible, so your staff (or clients) can +start populating data. Then, 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 encourages beautiful URL design and doesn't put any cruft +in URLs, like ``.php`` or ``.asp``. + +To design URLs for an app, you create a Python module called a :doc:`URLconf +`. A table of contents for your app, it contains a simple mapping +between URL patterns and Python callback functions. URLconfs also serve to +decouple URLs from Python code. + +Here's what a URLconf might look like for the ``Reporter``/``Article`` +example above:: + + from django.conf.urls.defaults import * + + urlpatterns = patterns('', + (r'^articles/(\d{4})/$', 'news.views.year_archive'), + (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'), + (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'), + ) + +The code above maps URLs, as simple 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 pattern, in order, and stops at the first one that matches the +requested URL. (If none of them matches, Django calls a special-case 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 the values captured in the regex. + +For example, if a user requested the URL "/articles/2005/05/39323/", Django +would call the function ``news.views.article_detail(request, +'2005', '05', '39323')``. + +Write your views +================ + +Each view is responsible for doing one of two things: Returning an +:class:`~django.http.HttpResponse` object containing the content for the +requested page, or raising an exception such as :class:`~django.http.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 +``year_archive`` from above:: + + def year_archive(request, year): + a_list = Article.objects.filter(pub_date__year=year) + return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list}) + +This example uses Django's :doc:`template system `, which has +several powerful features but strives to stay simple enough for non-programmers +to use. + +Design your templates +===================== + +The code above loads the ``news/year_archive.html`` 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.html`` template was found. Here's what that +might look like: + +.. code-block:: html+django + + {% extends "base.html" %} + + {% block title %}Articles for {{ year }}{% endblock %} + + {% block content %} +

Articles for {{ year }}

+ + {% for article in article_list %} +

{{ article.headline }}

+

By {{ article.reporter.full_name }}

+

Published {{ article.pub_date|date:"F j, Y" }}

+ {% endfor %} + {% endblock %} + +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. + +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.html" %}`` 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.html" template might look like: + +.. code-block:: html+django + + + + {% block title %}{% endblock %} + + + Logo + {% block content %}{% endblock %} + + + +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. + +It also lets you create multiple versions of a site, with different base +templates, while reusing child templates. Django's creators have used this +technique to create strikingly different cell-phone editions of sites -- simply +by creating a new 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 database 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 :doc:`caching framework ` that integrates with memcached + or other backends. + + * A :doc:`syndication framework ` that makes + creating RSS and Atom 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 :doc:`the +tutorial ` and join `the community`_. Thanks for your +interest! + +.. _download Django: http://www.djangoproject.com/download/ +.. _the community: http://www.djangoproject.com/community/ diff --git a/parts/django/docs/intro/tutorial01.txt b/parts/django/docs/intro/tutorial01.txt new file mode 100644 index 0000000..560070b --- /dev/null +++ b/parts/django/docs/intro/tutorial01.txt @@ -0,0 +1,690 @@ +===================================== +Writing your first Django app, part 1 +===================================== + +Let's learn by example. + +Throughout this tutorial, we'll walk you through the creation of a basic +poll application. + +It'll consist of two parts: + + * A public site that lets people view polls and vote in them. + * An admin site that lets you add, change and delete polls. + +We'll assume you have :doc:`Django installed ` already. You can +tell Django is installed by running the Python interactive interpreter and +typing ``import django``. If that command runs successfully, with no errors, +Django is installed. + +.. admonition:: Where to get help: + + If you're having trouble going through this tutorial, please post a message + to `django-users`__ or drop by `#django on irc.freenode.net`__ to chat + with other Django users who might be able to help. + +__ http://groups.google.com/group/django-users +__ irc://irc.freenode.net/django + +Creating a project +================== + +If this is your first time using Django, you'll have to take care of some +initial setup. Namely, you'll need to auto-generate some code that establishes a +Django :term:`project` -- a collection of settings for an instance of Django, +including database configuration, Django-specific options and +application-specific settings. + +From the command line, ``cd`` into a directory where you'd like to store your +code, then run the command ``django-admin.py startproject mysite``. This will +create a ``mysite`` directory in your current directory. + +.. admonition:: Script name may differ in distribution packages + + If you installed Django using a Linux distribution's package manager + (e.g. apt-get or yum) ``django-admin.py`` may have been renamed to + ``django-admin``. You may continue through this documentation by omitting + ``.py`` from each command. + +.. admonition:: Mac OS X permissions + + If you're using Mac OS X, you may see the message "permission denied" when + you try to run ``django-admin.py startproject``. This is because, on + Unix-based systems like OS X, a file must be marked as "executable" before it + can be run as a program. To do this, open Terminal.app and navigate (using + the ``cd`` command) to the directory where :doc:`django-admin.py + ` is installed, then run the command + ``chmod +x django-admin.py``. + +.. note:: + + You'll need to avoid naming projects after built-in Python or Django + components. In particular, this means you should avoid using names like + ``django`` (which will conflict with Django itself) or ``test`` (which + conflicts with a built-in Python package). + +:doc:`django-admin.py ` should be on your system path if you +installed Django via ``python setup.py``. If it's not on your path, you can find +it in ``site-packages/django/bin``, where ```site-packages``` is a directory +within your Python installation. Consider symlinking to :doc:`django-admin.py +` from some place on your path, such as +:file:`/usr/local/bin`. + +.. admonition:: Where should this code live? + + If your background is in PHP, you're probably used to putting code under the + Web server's document root (in a place such as ``/var/www``). With Django, + you don't do that. It's not a good idea to put any of this Python code + within your Web server's document root, because it risks the possibility + that people may be able to view your code over the Web. That's not good for + security. + + Put your code in some directory **outside** of the document root, such as + :file:`/home/mycode`. + +Let's look at what :djadmin:`startproject` created:: + + mysite/ + __init__.py + manage.py + settings.py + urls.py + +These files are: + + * :file:`__init__.py`: An empty file that tells Python that this directory + should be considered a Python package. (Read `more about packages`_ in the + official Python docs if you're a Python beginner.) + + * :file:`manage.py`: A command-line utility that lets you interact with this + Django project in various ways. You can read all the details about + :file:`manage.py` in :doc:`/ref/django-admin`. + + * :file:`settings.py`: Settings/configuration for this Django project. + :doc:`/topics/settings` will tell you all about how settings work. + + * :file:`urls.py`: The URL declarations for this Django project; a "table of + contents" of your Django-powered site. You can read more about URLs in + :doc:`/topics/http/urls`. + +.. _more about packages: http://docs.python.org/tutorial/modules.html#packages + +The development server +---------------------- + +Let's verify this worked. Change into the :file:`mysite` directory, if you +haven't already, and run the command ``python manage.py runserver``. You'll see +the following output on the command line:: + + Validating models... + 0 errors found. + + Django version 1.0, using settings 'mysite.settings' + Development server is running at http://127.0.0.1:8000/ + Quit the server with CONTROL-C. + +You've started the Django development server, a lightweight Web server written +purely in Python. We've included this with Django so you can develop things +rapidly, without having to deal with configuring a production server -- such as +Apache -- until you're ready for production. + +Now's a good time to note: DON'T use this server in anything resembling a +production environment. It's intended only for use while developing. (We're in +the business of making Web frameworks, not Web servers.) + +Now that the server's running, visit http://127.0.0.1:8000/ with your Web +browser. You'll see a "Welcome to Django" page, in pleasant, light-blue pastel. +It worked! + +.. admonition:: Changing the port + + By default, the :djadmin:`runserver` command starts the development server + on the internal IP at port 8000. + + If you want to change the server's port, pass + it as a command-line argument. For instance, this command starts the server + on port 8080: + + .. code-block:: bash + + python manage.py runserver 8080 + + If you want to change the server's IP, pass it along with the port. So to + listen on all public IPs (useful if you want to show off your work on other + computers), use: + + .. code-block:: bash + + python manage.py runserver 0.0.0.0:8000 + + Full docs for the development server can be found in the + :djadmin:`runserver` reference. + +Database setup +-------------- + +Now, edit :file:`settings.py`. It's a normal Python module with +module-level variables representing Django settings. Change the +following keys in the :setting:`DATABASES` ``'default'`` item to match +your databases connection settings. + + * :setting:`ENGINE` -- Either + ``'django.db.backends.postgresql_psycopg2'``, + ``'django.db.backends.mysql'`` or + ``'django.db.backends.sqlite3'``. Other backends are + :setting:`also available `. + + * :setting:`NAME` -- The name of your database. If you're using + SQLite, the database will be a file on your computer; in that + case, :setting:`NAME` should be the full absolute path, + including filename, of that file. If the file doesn't exist, it + will automatically be created when you synchronize the database + for the first time (see below). + + When specifying the path, always use forward slashes, even on + Windows (e.g. ``C:/homes/user/mysite/sqlite3.db``). + + * :setting:`USER` -- Your database username (not used for SQLite). + + * :setting:`PASSWORD` -- Your database password (not used for + SQLite). + + * :setting:`HOST` -- The host your database is on. Leave this as + an empty string if your database server is on the same physical + machine (not used for SQLite). + +If you're new to databases, we recommend simply using SQLite (by +setting :setting:`ENGINE` to ``'django.db.backends.sqlite3'``). SQLite +is included as part of Python 2.5 and later, so you won't need to +install anything else. + +.. note:: + + If you're using PostgreSQL or MySQL, make sure you've created a database by + this point. Do that with "``CREATE DATABASE database_name;``" within your + database's interactive prompt. + + If you're using SQLite, you don't need to create anything beforehand - the + database file will be created automatically when it is needed. + +While you're editing :file:`settings.py`, take note of the +:setting:`INSTALLED_APPS` setting towards the bottom of the file. That variable +holds the names of all Django applications that are activated in this Django +instance. Apps can be used in multiple projects, and you can package and +distribute them for use by others in their projects. + +By default, :setting:`INSTALLED_APPS` contains the following apps, all of which +come with Django: + + * :mod:`django.contrib.auth` -- An authentication system. + + * :mod:`django.contrib.contenttypes` -- A framework for content types. + + * :mod:`django.contrib.sessions` -- A session framework. + + * :mod:`django.contrib.sites` -- A framework for managing multiple sites + with one Django installation. + + * :mod:`django.contrib.messages` -- A messaging framework. + +These applications are included by default as a convenience for the common case. + +Each of these applications makes use of at least one database table, though, +so we need to create the tables in the database before we can use them. To do +that, run the following command: + +.. code-block:: bash + + python manage.py syncdb + +The :djadmin:`syncdb` command looks at the :setting:`INSTALLED_APPS` setting and +creates any necessary database tables according to the database settings in your +:file:`settings.py` file. You'll see a message for each database table it +creates, and you'll get a prompt asking you if you'd like to create a superuser +account for the authentication system. Go ahead and do that. + +If you're interested, run the command-line client for your database and type +``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to +display the tables Django created. + +.. admonition:: For the minimalists + + Like we said above, the default applications are included for the common + case, but not everybody needs them. If you don't need any or all of them, + feel free to comment-out or delete the appropriate line(s) from + :setting:`INSTALLED_APPS` before running :djadmin:`syncdb`. The + :djadmin:`syncdb` command will only create tables for apps in + :setting:`INSTALLED_APPS`. + +.. _creating-models: + +Creating models +=============== + +Now that your environment -- a "project" -- is set up, you're set to start +doing work. + +Each application you write in Django consists of a Python package, somewhere +on your `Python path`_, that follows a certain convention. Django comes with a +utility that automatically generates the basic directory structure of an app, +so you can focus on writing code rather than creating directories. + +.. admonition:: Projects vs. apps + + What's the difference between a project and an app? An app is a Web + application that does something -- e.g., a Weblog system, a database of + public records or a simple poll app. A project is a collection of + configuration and apps for a particular Web site. A project can contain + multiple apps. An app can be in multiple projects. + +Your apps can live anywhere on your `Python path`_. In this tutorial, we'll +create our poll app in the :file:`mysite` directory for simplicity. + +To create your app, make sure you're in the :file:`mysite` directory and type +this command: + +.. code-block:: bash + + python manage.py startapp polls + +That'll create a directory :file:`polls`, which is laid out like this:: + + polls/ + __init__.py + models.py + tests.py + views.py + +This directory structure will house the poll application. + +The first step in writing a database Web app in Django is to define your models +-- essentially, your database layout, with additional metadata. + +.. admonition:: Philosophy + + A model is the single, definitive source of data about your data. It contains + the essential fields and behaviors of the data you're storing. Django follows + the :ref:`DRY Principle `. The goal is to define your data model in one + place and automatically derive things from it. + +In our simple poll app, we'll create two models: polls and choices. A poll has +a question and a publication date. A choice has two fields: the text of the +choice and a vote tally. Each choice is associated with a poll. + +These concepts are represented by simple Python classes. Edit the +:file:`polls/models.py` file so it looks like this:: + + from django.db import models + + class Poll(models.Model): + question = models.CharField(max_length=200) + pub_date = models.DateTimeField('date published') + + class Choice(models.Model): + poll = models.ForeignKey(Poll) + choice = models.CharField(max_length=200) + votes = models.IntegerField() + +The code is straightforward. Each model is represented by a class that +subclasses :class:`django.db.models.Model`. Each model has a number of class +variables, each of which represents a database field in the model. + +Each field is represented by an instance of a :class:`~django.db.models.Field` +class -- e.g., :class:`~django.db.models.CharField` for character fields and +:class:`~django.db.models.DateTimeField` for datetimes. This tells Django what +type of data each field holds. + +The name of each :class:`~django.db.models.Field` instance (e.g. ``question`` or +``pub_date`` ) is the field's name, in machine-friendly format. You'll use this +value in your Python code, and your database will use it as the column name. + +You can use an optional first positional argument to a +:class:`~django.db.models.Field` to designate a human-readable name. That's used +in a couple of introspective parts of Django, and it doubles as documentation. +If this field isn't provided, Django will use the machine-readable name. In this +example, we've only defined a human-readable name for ``Poll.pub_date``. For all +other fields in this model, the field's machine-readable name will suffice as +its human-readable name. + +Some :class:`~django.db.models.Field` classes have required elements. +:class:`~django.db.models.CharField`, for example, requires that you give it a +:attr:`~django.db.models.Field.max_length`. That's used not only in the database +schema, but in validation, as we'll soon see. + +Finally, note a relationship is defined, using +:class:`~django.db.models.ForeignKey`. That tells Django each Choice is related +to a single Poll. Django supports all the common database relationships: +many-to-ones, many-to-manys and one-to-ones. + +.. _`Python path`: http://docs.python.org/tutorial/modules.html#the-module-search-path + +Activating models +================= + +That small bit of model code gives Django a lot of information. With it, Django +is able to: + + * Create a database schema (``CREATE TABLE`` statements) for this app. + * Create a Python database-access API for accessing Poll and Choice objects. + +But first we need to tell our project that the ``polls`` app is installed. + +.. admonition:: Philosophy + + Django apps are "pluggable": You can use an app in multiple projects, and + you can distribute apps, because they don't have to be tied to a given + Django installation. + +Edit the :file:`settings.py` file again, and change the +:setting:`INSTALLED_APPS` setting to include the string ``'polls'``. So +it'll look like this:: + + INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'polls' + ) + +Now Django knows to include the ``polls`` app. Let's run another +command: + +.. code-block:: bash + + python manage.py sql polls + +You should see something similar to the following (the ``CREATE TABLE`` SQL +statements for the polls app): + +.. code-block:: sql + + BEGIN; + CREATE TABLE "polls_poll" ( + "id" serial NOT NULL PRIMARY KEY, + "question" varchar(200) NOT NULL, + "pub_date" timestamp with time zone NOT NULL + ); + CREATE TABLE "polls_choice" ( + "id" serial NOT NULL PRIMARY KEY, + "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"), + "choice" varchar(200) NOT NULL, + "votes" integer NOT NULL + ); + COMMIT; + +Note the following: + + * The exact output will vary depending on the database you are using. + + * Table names are automatically generated by combining the name of the app + (``polls``) and the lowercase name of the model -- ``poll`` and + ``choice``. (You can override this behavior.) + + * Primary keys (IDs) are added automatically. (You can override this, too.) + + * By convention, Django appends ``"_id"`` to the foreign key field name. + Yes, you can override this, as well. + + * The foreign key relationship is made explicit by a ``REFERENCES`` + statement. + + * It's tailored to the database you're using, so database-specific field + types such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or + ``integer primary key`` (SQLite) are handled for you automatically. Same + goes for quoting of field names -- e.g., using double quotes or single + quotes. The author of this tutorial runs PostgreSQL, so the example + output is in PostgreSQL syntax. + + * The :djadmin:`sql` command doesn't actually run the SQL in your database - + it just prints it to the screen so that you can see what SQL Django thinks + is required. If you wanted to, you could copy and paste this SQL into your + database prompt. However, as we will see shortly, Django provides an + easier way of committing the SQL to the database. + +If you're interested, also run the following commands: + + * :djadmin:`python manage.py validate ` -- Checks for any errors + in the construction of your models. + + * :djadmin:`python manage.py sqlcustom polls ` -- Outputs any + :ref:`custom SQL statements ` (such as table modifications or + constraints) that are defined for the application. + + * :djadmin:`python manage.py sqlclear polls ` -- Outputs the + necessary ``DROP TABLE`` statements for this app, according to which + tables already exist in your database (if any). + + * :djadmin:`python manage.py sqlindexes polls ` -- Outputs the + ``CREATE INDEX`` statements for this app. + + * :djadmin:`python manage.py sqlall polls ` -- A combination of all + the SQL from the :djadmin:`sql`, :djadmin:`sqlcustom`, and + :djadmin:`sqlindexes` commands. + +Looking at the output of those commands can help you understand what's actually +happening under the hood. + +Now, run :djadmin:`syncdb` again to create those model tables in your database: + +.. code-block:: bash + + python manage.py syncdb + +The :djadmin:`syncdb` command runs the sql from 'sqlall' on your database for +all apps in :setting:`INSTALLED_APPS` that don't already exist in your database. +This creates all the tables, initial data and indexes for any apps you have +added to your project since the last time you ran syncdb. :djadmin:`syncdb` can +be called as often as you like, and it will only ever create the tables that +don't exist. + +Read the :doc:`django-admin.py documentation ` for full +information on what the ``manage.py`` utility can do. + +Playing with the API +==================== + +Now, let's hop into the interactive Python shell and play around with the free +API Django gives you. To invoke the Python shell, use this command: + +.. code-block:: bash + + python manage.py shell + +We're using this instead of simply typing "python", because ``manage.py`` sets +up the project's environment for you. "Setting up the environment" involves two +things: + + * Putting ``polls`` on ``sys.path``. For flexibility, several pieces of + Django refer to projects in Python dotted-path notation (e.g. + ``'polls.models'``). In order for this to work, the ``polls`` + package has to be on ``sys.path``. + + We've already seen one example of this: the :setting:`INSTALLED_APPS` + setting is a list of packages in dotted-path notation. + + * Setting the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives + Django the path to your ``settings.py`` file. + +.. admonition:: Bypassing manage.py + + If you'd rather not use ``manage.py``, no problem. Just make sure ``mysite`` + and ``polls`` are at the root level on the Python path (i.e., ``import mysite`` + and ``import polls`` work) and set the ``DJANGO_SETTINGS_MODULE`` environment + variable to ``mysite.settings``. + + For more information on all of this, see the :doc:`django-admin.py + documentation `. + +Once you're in the shell, explore the :doc:`database API `:: + + >>> from polls.models import Poll, Choice # Import the model classes we just wrote. + + # No polls are in the system yet. + >>> Poll.objects.all() + [] + + # Create a new Poll. + >>> import datetime + >>> p = Poll(question="What's up?", pub_date=datetime.datetime.now()) + + # Save the object into the database. You have to call save() explicitly. + >>> p.save() + + # Now it has an ID. Note that this might say "1L" instead of "1", depending + # on which database you're using. That's no biggie; it just means your + # database backend prefers to return integers as Python long integer + # objects. + >>> p.id + 1 + + # Access database columns via Python attributes. + >>> p.question + "What's up?" + >>> p.pub_date + datetime.datetime(2007, 7, 15, 12, 00, 53) + + # Change values by changing the attributes, then calling save(). + >>> p.pub_date = datetime.datetime(2007, 4, 1, 0, 0) + >>> p.save() + + # objects.all() displays all the polls in the database. + >>> Poll.objects.all() + [] + + +Wait a minute. ```` is, utterly, an unhelpful representation +of this object. Let's fix that by editing the polls model (in the +``polls/models.py`` file) and adding a +:meth:`~django.db.models.Model.__unicode__` method to both ``Poll`` and +``Choice``:: + + class Poll(models.Model): + # ... + def __unicode__(self): + return self.question + + class Choice(models.Model): + # ... + def __unicode__(self): + return self.choice + +It's important to add :meth:`~django.db.models.Model.__unicode__` methods to +your models, not only for your own sanity when dealing with the interactive +prompt, but also because objects' representations are used throughout Django's +automatically-generated admin. + +.. admonition:: Why :meth:`~django.db.models.Model.__unicode__` and not + :meth:`~django.db.models.Model.__str__`? + + If you're familiar with Python, you might be in the habit of adding + :meth:`~django.db.models.Model.__str__` methods to your classes, not + :meth:`~django.db.models.Model.__unicode__` methods. We use + :meth:`~django.db.models.Model.__unicode__` here because Django models deal + with Unicode by default. All data stored in your database is converted to + Unicode when it's returned. + + Django models have a default :meth:`~django.db.models.Model.__str__` method + that calls :meth:`~django.db.models.Model.__unicode__` and converts the + result to a UTF-8 bytestring. This means that ``unicode(p)`` will return a + Unicode string, and ``str(p)`` will return a normal string, with characters + encoded as UTF-8. + + If all of this is jibberish to you, just remember to add + :meth:`~django.db.models.Model.__unicode__` methods to your models. With any + luck, things should Just Work for you. + +Note these are normal Python methods. Let's add a custom method, just for +demonstration:: + + import datetime + # ... + class Poll(models.Model): + # ... + def was_published_today(self): + return self.pub_date.date() == datetime.date.today() + +Note the addition of ``import datetime`` to reference Python's standard +``datetime`` module. + +Save these changes and start a new Python interactive shell by running +``python manage.py shell`` again:: + + >>> from polls.models import Poll, Choice + + # Make sure our __unicode__() addition worked. + >>> Poll.objects.all() + [] + + # Django provides a rich database lookup API that's entirely driven by + # keyword arguments. + >>> Poll.objects.filter(id=1) + [] + >>> Poll.objects.filter(question__startswith='What') + [] + + # Get the poll whose year is 2007. + >>> Poll.objects.get(pub_date__year=2007) + + + >>> Poll.objects.get(id=2) + Traceback (most recent call last): + ... + DoesNotExist: Poll matching query does not exist. + + # Lookup by a primary key is the most common case, so Django provides a + # shortcut for primary-key exact lookups. + # The following is identical to Poll.objects.get(id=1). + >>> Poll.objects.get(pk=1) + + + # Make sure our custom method worked. + >>> p = Poll.objects.get(pk=1) + >>> p.was_published_today() + False + + # Give the Poll a couple of Choices. The create call constructs a new + # choice object, does the INSERT statement, adds the choice to the set + # of available choices and returns the new Choice object. Django creates + # a set to hold the "other side" of a ForeignKey relation + # (e.g. a poll's choices) which can be accessed via the API. + >>> p = Poll.objects.get(pk=1) + + # Display any choices from the related object set -- none so far. + >>> p.choice_set.all() + [] + + # Create three choices. + >>> p.choice_set.create(choice='Not much', votes=0) + + >>> p.choice_set.create(choice='The sky', votes=0) + + >>> c = p.choice_set.create(choice='Just hacking again', votes=0) + + # Choice objects have API access to their related Poll objects. + >>> c.poll + + + # And vice versa: Poll objects get access to Choice objects. + >>> p.choice_set.all() + [, , ] + >>> p.choice_set.count() + 3 + + # The API automatically follows relationships as far as you need. + # Use double underscores to separate relationships. + # This works as many levels deep as you want; there's no limit. + # Find all Choices for any poll whose pub_date is in 2007. + >>> Choice.objects.filter(poll__pub_date__year=2007) + [, , ] + + # Let's delete one of the choices. Use delete() for that. + >>> c = p.choice_set.filter(choice__startswith='Just hacking') + >>> c.delete() + +For more information on model relations, see :doc:`Accessing related objects +`. For full details on the database API, see our +:doc:`Database API reference `. + +When you're comfortable with the API, read :doc:`part 2 of this tutorial +` to get Django's automatic admin working. diff --git a/parts/django/docs/intro/tutorial02.txt b/parts/django/docs/intro/tutorial02.txt new file mode 100644 index 0000000..c80d87d --- /dev/null +++ b/parts/django/docs/intro/tutorial02.txt @@ -0,0 +1,465 @@ +===================================== +Writing your first Django app, part 2 +===================================== + +This tutorial begins where :doc:`Tutorial 1 ` left off. We're +continuing the Web-poll application and will focus on Django's +automatically-generated admin site. + +.. admonition:: Philosophy + + Generating admin sites for your staff or clients to add, change and delete + content is tedious work that doesn't require much creativity. For that + reason, Django entirely automates creation of admin interfaces for models. + + Django was written in a newsroom environment, with a very clear separation + between "content publishers" and the "public" site. Site managers use the + system to add news stories, events, sports scores, etc., and that content is + displayed on the public site. Django solves the problem of creating a + unified interface for site administrators to edit content. + + The admin isn't necessarily intended to be used by site visitors; it's for + site managers. + +Activate the admin site +======================= + +The Django admin site is not activated by default -- it's an opt-in thing. To +activate the admin site for your installation, do these three things: + + * Add ``"django.contrib.admin"`` to your :setting:`INSTALLED_APPS` setting. + + * Run ``python manage.py syncdb``. Since you have added a new application + to :setting:`INSTALLED_APPS`, the database tables need to be updated. + + * Edit your ``mysite/urls.py`` file and uncomment the lines that reference + the admin -- there are three lines in total to uncomment. This file is a + URLconf; we'll dig into URLconfs in the next tutorial. For now, all you + need to know is that it maps URL roots to applications. In the end, you + should have a ``urls.py`` file that looks like this: + + .. versionchanged:: 1.1 + The method for adding admin urls has changed in Django 1.1. + + .. parsed-literal:: + + from django.conf.urls.defaults import * + + # Uncomment the next two lines to enable the admin: + **from django.contrib import admin** + **admin.autodiscover()** + + urlpatterns = patterns('', + # Example: + # (r'^mysite/', include('mysite.foo.urls')), + + # Uncomment the admin/doc line below and add 'django.contrib.admindocs' + # to INSTALLED_APPS to enable admin documentation: + # (r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + **(r'^admin/', include(admin.site.urls)),** + ) + + (The bold lines are the ones that needed to be uncommented.) + +Start the development server +============================ + +Let's start the development server and explore the admin site. + +Recall from Tutorial 1 that you start the development server like so: + +.. code-block:: bash + + python manage.py runserver + +Now, open a Web browser and go to "/admin/" on your local domain -- e.g., +http://127.0.0.1:8000/admin/. You should see the admin's login screen: + +.. image:: _images/admin01.png + :alt: Django admin login screen + +Enter the admin site +==================== + +Now, try logging in. (You created a superuser account in the first part of this +tutorial, remember? If you didn't create one or forgot the password you can +:ref:`create another one `.) You should see +the Django admin index page: + +.. image:: _images/admin02t.png + :alt: Django admin index page + +You should see a few other types of editable content, including groups, users +and sites. These are core features Django ships with by default. + +Make the poll app modifiable in the admin +========================================= + +But where's our poll app? It's not displayed on the admin index page. + +Just one thing to do: We need to tell the admin that ``Poll`` +objects have an admin interface. To do this, create a file called +``admin.py`` in your ``polls`` directory, and edit it to look like this:: + + from polls.models import Poll + from django.contrib import admin + + admin.site.register(Poll) + +You'll need to restart the development server to see your changes. Normally, +the server auto-reloads code every time you modify a file, but the action of +creating a new file doesn't trigger the auto-reloading logic. + +Explore the free admin functionality +==================================== + +Now that we've registered ``Poll``, Django knows that it should be displayed on +the admin index page: + +.. image:: _images/admin03t.png + :alt: Django admin index page, now with polls displayed + +Click "Polls." Now you're at the "change list" page for polls. This page +displays all the polls in the database and lets you choose one to change it. +There's the "What's up?" poll we created in the first tutorial: + +.. image:: _images/admin04t.png + :alt: Polls change list page + +Click the "What's up?" poll to edit it: + +.. image:: _images/admin05t.png + :alt: Editing form for poll object + +Things to note here: + + * The form is automatically generated from the Poll model. + + * The different model field types (:class:`~django.db.models.DateTimeField`, + :class:`~django.db.models.CharField`) correspond to the appropriate HTML + input widget. Each type of field knows how to display itself in the Django + admin. + + * Each :class:`~django.db.models.DateTimeField` gets free JavaScript + shortcuts. Dates get a "Today" shortcut and calendar popup, and times get + a "Now" shortcut and a convenient popup that lists commonly entered times. + +The bottom part of the page gives you a couple of options: + + * Save -- Saves changes and returns to the change-list page for this type of + object. + + * Save and continue editing -- Saves changes and reloads the admin page for + this object. + + * Save and add another -- Saves changes and loads a new, blank form for this + type of object. + + * Delete -- Displays a delete confirmation page. + +Change the "Date published" by clicking the "Today" and "Now" shortcuts. Then +click "Save and continue editing." Then click "History" in the upper right. +You'll see a page listing all changes made to this object via the Django admin, +with the timestamp and username of the person who made the change: + +.. image:: _images/admin06t.png + :alt: History page for poll object + +Customize the admin form +======================== + +Take a few minutes to marvel at all the code you didn't have to write. By +registering the Poll model with ``admin.site.register(Poll)``, Django was able +to construct a default form representation. Often, you'll want to customize how +the admin form looks and works. You'll do this by telling Django the options +you want when you register the object. + +Let's see how this works by re-ordering the fields on the edit form. Replace +the ``admin.site.register(Poll)`` line with:: + + class PollAdmin(admin.ModelAdmin): + fields = ['pub_date', 'question'] + + admin.site.register(Poll, PollAdmin) + +You'll follow this pattern -- create a model admin object, then pass it as the +second argument to ``admin.site.register()`` -- any time you need to change the +admin options for an object. + +This particular change above makes the "Publication date" come before the +"Question" field: + +.. image:: _images/admin07.png + :alt: Fields have been reordered + +This isn't impressive with only two fields, but for admin forms with dozens +of fields, choosing an intuitive order is an important usability detail. + +And speaking of forms with dozens of fields, you might want to split the form +up into fieldsets:: + + class PollAdmin(admin.ModelAdmin): + fieldsets = [ + (None, {'fields': ['question']}), + ('Date information', {'fields': ['pub_date']}), + ] + + admin.site.register(Poll, PollAdmin) + +The first element of each tuple in ``fieldsets`` is the title of the fieldset. +Here's what our form looks like now: + +.. image:: _images/admin08t.png + :alt: Form has fieldsets now + +You can assign arbitrary HTML classes to each fieldset. Django provides a +``"collapse"`` class that displays a particular fieldset initially collapsed. +This is useful when you have a long form that contains a number of fields that +aren't commonly used:: + + class PollAdmin(admin.ModelAdmin): + fieldsets = [ + (None, {'fields': ['question']}), + ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), + ] + +.. image:: _images/admin09.png + :alt: Fieldset is initially collapsed + +Adding related objects +====================== + +OK, we have our Poll admin page. But a ``Poll`` has multiple ``Choices``, and +the admin page doesn't display choices. + +Yet. + +There are two ways to solve this problem. The first is to register ``Choice`` +with the admin just as we did with ``Poll``. That's easy:: + + from polls.models import Choice + + admin.site.register(Choice) + +Now "Choices" is an available option in the Django admin. The "Add choice" form +looks like this: + +.. image:: _images/admin10.png + :alt: Choice admin page + +In that form, the "Poll" field is a select box containing every poll in the +database. Django knows that a :class:`~django.db.models.ForeignKey` should be +represented in the admin as a `` +
+ {% endfor %} + + + +A quick rundown: + + * The above template displays a radio button for each poll choice. The + ``value`` of each radio button is the associated poll choice's ID. The + ``name`` of each radio button is ``"choice"``. That means, when somebody + selects one of the radio buttons and submits the form, it'll send the + POST data ``choice=3``. This is HTML Forms 101. + + * We set the form's ``action`` to ``/polls/{{ poll.id }}/vote/``, and we + set ``method="post"``. Using ``method="post"`` (as opposed to + ``method="get"``) is very important, because the act of submitting this + form will alter data server-side. Whenever you create a form that alters + data server-side, use ``method="post"``. This tip isn't specific to + Django; it's just good Web development practice. + + * ``forloop.counter`` indicates how many times the :ttag:`for` tag has gone + through its loop + + * Since we're creating a POST form (which can have the effect of modifying + data), we need to worry about Cross Site Request Forgeries. + Thankfully, you don't have to worry too hard, because Django comes with + a very easy-to-use system for protecting against it. In short, all POST + forms that are targeted at internal URLs should use the ``{% csrf_token %}`` + template tag. + +The ``{% csrf_token %}`` tag requires information from the request object, which +is not normally accessible from within the template context. To fix this, a +small adjustment needs to be made to the ``detail`` view, so that it looks like +the following:: + + from django.template import RequestContext + # ... + def detail(request, poll_id): + p = get_object_or_404(Poll, pk=poll_id) + return render_to_response('polls/detail.html', {'poll': p}, + context_instance=RequestContext(request)) + +The details of how this works are explained in the documentation for +:ref:`RequestContext `. + +Now, let's create a Django view that handles the submitted data and does +something with it. Remember, in :doc:`Tutorial 3 `, we +created a URLconf for the polls application that includes this line:: + + (r'^(?P\d+)/vote/$', 'vote'), + +We also created a dummy implementation of the ``vote()`` function. Let's +create a real version. Add the following to ``polls/views.py``:: + + from django.shortcuts import get_object_or_404, render_to_response + from django.http import HttpResponseRedirect, HttpResponse + from django.core.urlresolvers import reverse + from django.template import RequestContext + from 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.", + }, context_instance=RequestContext(request)) + 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('polls.views.results', args=(p.id,))) + +This code includes a few things we haven't covered yet in this tutorial: + + * :attr:`request.POST ` is a dictionary-like + object that lets you access submitted data by key name. In this case, + ``request.POST['choice']`` returns the ID of the selected choice, as a + string. :attr:`request.POST ` values are + always strings. + + Note that Django also provides :attr:`request.GET + ` for accessing GET data in the same way -- + but we're explicitly using :attr:`request.POST + ` in our code, to ensure that data is only + altered via a POST call. + + * ``request.POST['choice']`` will raise :exc:`KeyError` if ``choice`` wasn't + provided in POST data. The above code checks for :exc:`KeyError` and + redisplays the poll form with an error message if ``choice`` isn't given. + + * After incrementing the choice count, the code returns an + :class:`~django.http.HttpResponseRedirect` rather than a normal + :class:`~django.http.HttpResponse`. + :class:`~django.http.HttpResponseRedirect` takes a single argument: the + URL to which the user will be redirected (see the following point for how + we construct the URL in this case). + + As the Python comment above points out, you should always return an + :class:`~django.http.HttpResponseRedirect` after successfully dealing with + POST data. This tip isn't specific to Django; it's just good Web + development practice. + + * We are using the :func:`~django.core.urlresolvers.reverse` function in the + :class:`~django.http.HttpResponseRedirect` constructor in this example. + This function helps avoid having to hardcode a URL in the view function. + It is given the name of the view that we want to pass control to and the + variable portion of the URL pattern that points to that view. In this + case, using the URLconf we set up in Tutorial 3, this + :func:`~django.core.urlresolvers.reverse` call will return a string like + :: + + '/polls/3/results/' + + ... where the ``3`` is the value of ``p.id``. This redirected URL will + then call the ``'results'`` view to display the final page. Note that you + need to use the full name of the view here (including the prefix). + +As mentioned in Tutorial 3, ``request`` is a :class:`~django.http.HttpRequest` +object. For more on :class:`~django.http.HttpRequest` objects, see the +:doc:`request and response documentation `. + +After somebody votes in a poll, the ``vote()`` view redirects to the results +page for the poll. Let's write that view:: + + def results(request, poll_id): + p = get_object_or_404(Poll, pk=poll_id) + return render_to_response('polls/results.html', {'poll': p}) + +This is almost exactly the same as the ``detail()`` view from :doc:`Tutorial 3 +`. The only difference is the template name. We'll fix this +redundancy later. + +Now, create a ``results.html`` template: + +.. code-block:: html+django + +

{{ poll.question }}

+ +
    + {% for choice in poll.choice_set.all %} +
  • {{ choice.choice }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}
  • + {% endfor %} +
+ + Vote again? + +Now, go to ``/polls/1/`` in your browser and vote in the poll. You should see a +results page that gets updated each time you vote. If you submit the form +without having chosen a choice, you should see the error message. + +Use generic views: Less code is better +====================================== + +The ``detail()`` (from :doc:`Tutorial 3 `) and ``results()`` +views are stupidly simple -- and, as mentioned above, redundant. The ``index()`` +view (also from Tutorial 3), which displays a list of polls, is similar. + +These views represent a common case of basic Web development: getting data from +the database according to a parameter passed in the URL, loading a template and +returning the rendered template. Because this is so common, Django provides a +shortcut, called the "generic views" system. + +Generic views abstract common patterns to the point where you don't even need +to write Python code to write an app. + +Let's convert our poll app to use the generic views system, so we can delete a +bunch of our own code. We'll just have to take a few steps to make the +conversion. We will: + + 1. Convert the URLconf. + + 2. Rename a few templates. + + 3. Delete some of the old, unneeded views. + + 4. Fix up URL handling for the new views. + +Read on for details. + +.. admonition:: Why the code-shuffle? + + Generally, when writing a Django app, you'll evaluate whether generic views + are a good fit for your problem, and you'll use them from the beginning, + rather than refactoring your code halfway through. But this tutorial + intentionally has focused on writing the views "the hard way" until now, to + focus on core concepts. + + You should know basic math before you start using a calculator. + +First, open the ``polls/urls.py`` URLconf. It looks like this, according to the +tutorial so far:: + + from django.conf.urls.defaults import * + + urlpatterns = patterns('polls.views', + (r'^$', 'index'), + (r'^(?P\d+)/$', 'detail'), + (r'^(?P\d+)/results/$', 'results'), + (r'^(?P\d+)/vote/$', 'vote'), + ) + +Change it like so:: + + from django.conf.urls.defaults import * + from polls.models import Poll + + info_dict = { + 'queryset': Poll.objects.all(), + } + + urlpatterns = patterns('', + (r'^$', 'django.views.generic.list_detail.object_list', info_dict), + (r'^(?P\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict), + url(r'^(?P\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results.html'), 'poll_results'), + (r'^(?P\d+)/vote/$', 'polls.views.vote'), + ) + +We're using two generic views here: +:func:`~django.views.generic.list_detail.object_list` and +:func:`~django.views.generic.list_detail.object_detail`. Respectively, those two +views abstract the concepts of "display a list of objects" and "display a detail +page for a particular type of object." + + * Each generic view needs to know what data it will be acting upon. This + data is provided in a dictionary. The ``queryset`` key in this dictionary + points to the list of objects to be manipulated by the generic view. + + * The :func:`~django.views.generic.list_detail.object_detail` generic view + expects the ID value captured from the URL to be called ``"object_id"``, + so we've changed ``poll_id`` to ``object_id`` for the generic views. + + * We've added a name, ``poll_results``, to the results view so that we have + a way to refer to its URL later on (see the documentation about + :ref:`naming URL patterns ` for information). We're + also using the :func:`~django.conf.urls.default.url` function from + :mod:`django.conf.urls.defaults` here. It's a good habit to use + :func:`~django.conf.urls.defaults.url` when you are providing a pattern + name like this. + +By default, the :func:`~django.views.generic.list_detail.object_detail` generic +view uses a template called ``/_detail.html``. In our +case, it'll use the template ``"polls/poll_detail.html"``. Thus, rename your +``polls/detail.html`` template to ``polls/poll_detail.html``, and change the +:func:`~django.shortcuts.render_to_response` line in ``vote()``. + +Similarly, the :func:`~django.views.generic.list_detail.object_list` generic +view uses a template called ``/_list.html``. Thus, rename +``polls/index.html`` to ``polls/poll_list.html``. + +Because we have more than one entry in the URLconf that uses +:func:`~django.views.generic.list_detail.object_detail` for the polls app, we +manually specify a template name for the results view: +``template_name='polls/results.html'``. Otherwise, both views would use the same +template. Note that we use ``dict()`` to return an altered dictionary in place. + +.. note:: :meth:`django.db.models.QuerySet.all` is lazy + + It might look a little frightening to see ``Poll.objects.all()`` being used + in a detail view which only needs one ``Poll`` object, but don't worry; + ``Poll.objects.all()`` is actually a special object called a + :class:`~django.db.models.QuerySet`, which is "lazy" and doesn't hit your + database until it absolutely has to. By the time the database query happens, + the :func:`~django.views.generic.list_detail.object_detail` generic view + will have narrowed its scope down to a single object, so the eventual query + will only select one row from the database. + + If you'd like to know more about how that works, The Django database API + documentation :ref:`explains the lazy nature of QuerySet objects + `. + +In previous parts of the tutorial, the templates have been provided with a +context that contains the ``poll`` and ``latest_poll_list`` context variables. +However, the generic views provide the variables ``object`` and ``object_list`` +as context. Therefore, you need to change your templates to match the new +context variables. Go through your templates, and modify any reference to +``latest_poll_list`` to ``object_list``, and change any reference to ``poll`` +to ``object``. + +You can now delete the ``index()``, ``detail()`` and ``results()`` views +from ``polls/views.py``. We don't need them anymore -- they have been replaced +by generic views. + +The ``vote()`` view is still required. However, it must be modified to match the +new context variables. In the :func:`~django.shortcuts.render_to_response` call, +rename the ``poll`` context variable to ``object``. + +The last thing to do is fix the URL handling to account for the use of generic +views. In the vote view above, we used the +:func:`~django.core.urlresolvers.reverse` function to avoid hard-coding our +URLs. Now that we've switched to a generic view, we'll need to change the +:func:`~django.core.urlresolvers.reverse` call to point back to our new generic +view. We can't simply use the view function anymore -- generic views can be (and +are) used multiple times -- but we can use the name we've given:: + + return HttpResponseRedirect(reverse('poll_results', args=(p.id,))) + +Run the server, and use your new polling app based on generic views. + +For full details on generic views, see the :doc:`generic views documentation +`. + +Coming soon +=========== + +The tutorial ends here for the time being. Future installments of the tutorial +will cover: + + * Advanced form processing + * Using the RSS framework + * Using the cache framework + * Using the comments framework + * Advanced admin features: Permissions + * Advanced admin features: Custom JavaScript + +In the meantime, you might want to check out some pointers on :doc:`where to go +from here ` diff --git a/parts/django/docs/intro/whatsnext.txt b/parts/django/docs/intro/whatsnext.txt new file mode 100644 index 0000000..00c1654 --- /dev/null +++ b/parts/django/docs/intro/whatsnext.txt @@ -0,0 +1,231 @@ +================= +What to read next +================= + +So you've read all the :doc:`introductory material ` and have +decided you'd like to keep using Django. We've only just scratched the surface +with this intro (in fact, if you've read every single word you've still read +less than 10% of the overall documentation). + +So what's next? + +Well, we've always been big fans of learning by doing. At this point you should +know enough to start a project of your own and start fooling around. As you need +to learn new tricks, come back to the documentation. + +We've put a lot of effort into making Django's documentation useful, easy to +read and as complete as possible. The rest of this document explains more about +how the documentation works so that you can get the most out of it. + +(Yes, this is documentation about documentation. Rest assured we have no plans +to write a document about how to read the document about documentation.) + +Finding documentation +===================== + +Django's got a *lot* of documentation -- almost 200,000 words -- so finding what +you need can sometimes be tricky. A few good places to start are the :ref:`search` +and the :ref:`genindex`. + +Or you can just browse around! + +How the documentation is organized +================================== + +Django's main documentation is broken up into "chunks" designed to fill +different needs: + + * The :doc:`introductory material ` is designed for people new + to Django -- or to Web development in general. It doesn't cover anything + in depth, but instead gives a high-level overview of how developing in + Django "feels". + + * The :doc:`topic guides `, on the other hand, dive deep into + individual parts of Django. There are complete guides to Django's + :doc:`model system `, :doc:`template engine + `, :doc:`forms framework `, and much + more. + + This is probably where you'll want to spend most of your time; if you work + your way through these guides you should come out knowing pretty much + everything there is to know about Django. + + * Web development is often broad, not deep -- problems span many domains. + We've written a set of :doc:`how-to guides ` that answer + common "How do I ...?" questions. Here you'll find information about + :doc:`generating PDFs with Django `, :doc:`writing + custom template tags `, and more. + + Answers to really common questions can also be found in the :doc:`FAQ + `. + + * The guides and how-to's don't cover every single class, function, and + method available in Django -- that would be overwhelming when you're + trying to learn. Instead, details about individual classes, functions, + methods, and modules are kept in the :doc:`reference `. This is + where you'll turn to find the details of a particular function or + whathaveyou. + + * Finally, there's some "specialized" documentation not usually relevant to + most developers. This includes the :doc:`release notes `, + :doc:`documentation of obsolete features `, + :doc:`internals documentation ` for those who want to add + code to Django itself, and a :doc:`few other things that simply don't fit + elsewhere `. + + +How documentation is updated +============================ + +Just as the Django code base is developed and improved on a daily basis, our +documentation is consistently improving. We improve documentation for several +reasons: + + * To make content fixes, such as grammar/typo corrections. + + * To add information and/or examples to existing sections that need to be + expanded. + + * To document Django features that aren't yet documented. (The list of + such features is shrinking but exists nonetheless.) + + * To add documentation for new features as new features get added, or as + Django APIs or behaviors change. + +Django's documentation is kept in the same source control system as its code. It +lives in the `django/trunk/docs`_ directory of our Subversion repository. Each +document online is a separate text file in the repository. + +.. _django/trunk/docs: http://code.djangoproject.com/browser/django/trunk/docs + +Where to get it +=============== + +You can read Django documentation in several ways. They are, in order of +preference: + +On the Web +---------- + +The most recent version of the Django documentation lives at +http://docs.djangoproject.com/en/dev/. These HTML pages are generated +automatically from the text files in source control. That means they reflect the +"latest and greatest" in Django -- they include the very latest corrections and +additions, and they discuss the latest Django features, which may only be +available to users of the Django development version. (See "Differences between +versions" below.) + +We encourage you to help improve the docs by submitting changes, corrections and +suggestions in the `ticket system`_. The Django developers actively monitor the +ticket system and use your feedback to improve the documentation for everybody. + +Note, however, that tickets should explicitly relate to the documentation, +rather than asking broad tech-support questions. If you need help with your +particular Django setup, try the `django-users mailing list`_ or the `#django +IRC channel`_ instead. + +.. _ticket system: http://code.djangoproject.com/simpleticket?component=Documentation +.. _django-users mailing list: http://groups.google.com/group/django-users +.. _#django IRC channel: irc://irc.freenode.net/django + +In plain text +------------- + +For offline reading, or just for convenience, you can read the Django +documentation in plain text. + +If you're using an official release of Django, note that the zipped package +(tarball) of the code includes a ``docs/`` directory, which contains all the +documentation for that release. + +If you're using the development version of Django (aka the Subversion "trunk"), +note that the ``docs/`` directory contains all of the documentation. You can +``svn update`` it, just as you ``svn update`` the Python code, in order to get +the latest changes. + +You can check out the latest Django documentation from Subversion using this +shell command: + +.. code-block:: bash + + $ svn co http://code.djangoproject.com/svn/django/trunk/docs/ django_docs + +One low-tech way of taking advantage of the text documentation is by using the +Unix ``grep`` utility to search for a phrase in all of the documentation. For +example, this will show you each mention of the phrase "max_length" in any +Django document: + +.. code-block:: bash + + $ grep -r max_length /path/to/django/docs/ + +As HTML, locally +---------------- + +You can get a local copy of the HTML documentation following a few easy steps: + + * Django's documentation uses a system called Sphinx__ to convert from + plain text to HTML. You'll need to install Sphinx by either downloading + and installing the package from the Sphinx Web site, or by Python's + ``easy_install``: + + .. code-block:: bash + + $ easy_install Sphinx + + * Then, just use the included ``Makefile`` to turn the documentation into + HTML: + + .. code-block:: bash + + $ cd path/to/django/docs + $ make html + + You'll need `GNU Make`__ installed for this. + + * The HTML documentation will be placed in ``docs/_build/html``. + +.. note:: + + Generation of the Django documentation will work with Sphinx version 0.6 + or newer, but we recommend going straight to Sphinx 1.0.2 or newer. + +__ http://sphinx.pocoo.org/ +__ http://www.gnu.org/software/make/ + +Differences between versions +============================ + +As previously mentioned, the text documentation in our Subversion repository +contains the "latest and greatest" changes and additions. These changes often +include documentation of new features added in the Django development version +-- the Subversion ("trunk") version of Django. For that reason, it's worth +pointing out our policy on keeping straight the documentation for various +versions of the framework. + +We follow this policy: + + * The primary documentation on djangoproject.com is an HTML version of the + latest docs in Subversion. These docs always correspond to the latest + official Django release, plus whatever features we've added/changed in + the framework *since* the latest release. + + * As we add features to Django's development version, we try to update the + documentation in the same Subversion commit transaction. + + * To distinguish feature changes/additions in the docs, we use the phrase: + "New in version X.Y", being X.Y the next release version (hence, the one + being developed). + + * Documentation for a particular Django release is frozen once the version + has been released officially. It remains a snapshot of the docs as of the + moment of the release. We will make exceptions to this rule in + the case of retroactive security updates or other such retroactive + changes. Once documentation is frozen, we add a note to the top of each + frozen document that says "These docs are frozen for Django version XXX" + and links to the current version of that document. + + * The `main documentation Web page`_ includes links to documentation for + all previous versions. + +.. _main documentation Web page: http://docs.djangoproject.com/en/dev/ -- cgit