From 2052b508eb92c62fc0678efd4936c5ec1e0e735b Mon Sep 17 00:00:00 2001 From: Justin Bronn Date: Sun, 26 Aug 2007 01:10:53 +0000 Subject: gis: Made necessary modifications for unicode, manage refactor, backend refactor and merged 5584-6000 via svnmerge from [repos:django/trunk trunk]. git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6018 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- docs/add_ons.txt | 25 +- docs/api_stability.txt | 5 +- docs/authentication.txt | 33 +- docs/cache.txt | 2 +- docs/contributing.txt | 96 ++-- docs/csrf.txt | 10 +- docs/databases.txt | 2 +- docs/databrowse.txt | 1 + docs/db-api.txt | 113 ++++- docs/distributions.txt | 24 +- docs/django-admin.txt | 55 +- docs/email.txt | 2 +- docs/faq.txt | 3 + docs/fastcgi.txt | 2 +- docs/forms.txt | 12 +- docs/generic_views.txt | 10 +- docs/i18n.txt | 178 +++++-- docs/install.txt | 32 +- docs/man/compile-messages.1 | 40 ++ docs/man/daily_cleanup.1 | 34 ++ docs/man/gather_profile_stats.1 | 26 + docs/man/make-messages.1 | 62 +++ docs/middleware.txt | 14 + docs/model-api.txt | 294 ++++++++--- docs/modpython.txt | 28 +- docs/newforms.txt | 379 +++++++++++++- docs/overview.txt | 28 +- docs/release_notes_0.95.txt | 2 +- docs/request_response.txt | 26 +- docs/sessions.txt | 6 + docs/settings.txt | 19 + docs/sitemaps.txt | 2 +- docs/sites.txt | 28 +- docs/static_files.txt | 8 +- docs/syndication_feeds.txt | 50 +- docs/templates.txt | 122 ++++- docs/templates_python.txt | 11 +- docs/testing.txt | 1068 +++++++++++++++++++++++++-------------- docs/tutorial01.txt | 69 ++- docs/tutorial02.txt | 8 +- docs/tutorial03.txt | 5 +- docs/tutorial04.txt | 24 +- docs/unicode.txt | 364 +++++++++++++ docs/url_dispatch.txt | 24 +- 44 files changed, 2620 insertions(+), 726 deletions(-) create mode 100644 docs/man/compile-messages.1 create mode 100644 docs/man/daily_cleanup.1 create mode 100644 docs/man/gather_profile_stats.1 create mode 100644 docs/man/make-messages.1 create mode 100644 docs/unicode.txt (limited to 'docs') diff --git a/docs/add_ons.txt b/docs/add_ons.txt index ffc4f7420f..a1d78b8685 100644 --- a/docs/add_ons.txt +++ b/docs/add_ons.txt @@ -138,6 +138,29 @@ Examples: You can pass in either an integer or a string representation of an integer. +naturalday +---------- + +**New in Django development version** + +For dates that are the current day or within one day, return "today", +"tomorrow" or "yesterday", as appropriate. Otherwise, format the date using +the passed in format string. + +**Argument:** Date formatting string as described in default tag now_. + +.. _now: ../templates/#now + +Examples (when 'today' is 17 Feb 2007): + + * ``16 Feb 2007`` becomes ``yesterday``. + * ``17 Feb 2007`` becomes ``today``. + * ``18 Feb 2007`` becomes ``tomorrow``. + * Any other day is formatted according to given argument or the + `DATE_FORMAT`_ setting if no argument is given. + +.. _DATE_FORMAT: ../settings/#date_format + flatpages ========= @@ -214,7 +237,7 @@ A framework for generating syndication feeds, in RSS and Atom, quite easily. See the `syndication documentation`_. -.. _syndication documentation: ../syndication/ +.. _syndication documentation: ../syndication_feeds/ Other add-ons ============= diff --git a/docs/api_stability.txt b/docs/api_stability.txt index cfaffeac6b..5ccf104327 100644 --- a/docs/api_stability.txt +++ b/docs/api_stability.txt @@ -82,9 +82,6 @@ that 90% of Django can be considered forwards-compatible at this point. That said, these APIs should *not* be considered stable, and are likely to change: - - `Forms and validation`_ will most likely be completely rewritten to - deemphasize Manipulators in favor of validation-aware models. - - `Serialization`_ is under heavy development; changes are likely. - The `authentication`_ framework is changing to be far more flexible, and @@ -114,7 +111,7 @@ change: .. _sending email: ../email/ .. _sessions: ../sessions/ .. _settings: ../settings/ -.. _syndication: ../syndication/ +.. _syndication: ../syndication_feeds/ .. _template language: ../templates/ .. _transactions: ../transactions/ .. _url dispatch: ../url_dispatch/ diff --git a/docs/authentication.txt b/docs/authentication.txt index efe4d47513..7860b59d7d 100644 --- a/docs/authentication.txt +++ b/docs/authentication.txt @@ -99,7 +99,7 @@ custom methods: should prefer using ``is_authenticated()`` to this method. * ``is_authenticated()`` -- Always returns ``True``. This is a way to - tell if the user has been authenticated. This does not imply any + tell if the user has been authenticated. This does not imply any permissions, and doesn't check if the user is active - it only indicates that the user has provided a valid username and password. @@ -114,6 +114,18 @@ custom methods: string is the correct password for the user. (This takes care of the password hashing in making the comparison.) + * ``set_unusable_password()`` -- **New in Django development version.** + Marks the user as having no password set. This isn't the same as having + a blank string for a password. ``check_password()`` for this user will + never return ``True``. Doesn't save the ``User`` object. + + You may need this if authentication for your application takes place + against an existing external source such as an LDAP directory. + + * ``has_usable_password()`` -- **New in Django development version.** + Returns ``False`` if ``set_unusable_password()`` has been called for this + user. + * ``get_group_permissions()`` -- Returns a list of permission strings that the user has, through his/her groups. @@ -126,7 +138,7 @@ custom methods: * ``has_perms(perm_list)`` -- Returns ``True`` if the user has each of the specified permissions, where each perm is in the format - ``"package.codename"``. If the user is inactive, this method will + ``"package.codename"``. If the user is inactive, this method will always return ``False``. * ``has_module_perms(package_name)`` -- Returns ``True`` if the user has @@ -152,9 +164,11 @@ Manager functions The ``User`` model has a custom manager that has the following helper functions: - * ``create_user(username, email, password)`` -- Creates, saves and returns - a ``User``. The ``username``, ``email`` and ``password`` are set as - given, and the ``User`` gets ``is_active=True``. + * ``create_user(username, email, password=None)`` -- Creates, saves and + returns a ``User``. The ``username``, ``email`` and ``password`` are set + as given, and the ``User`` gets ``is_active=True``. + + If no password is provided, ``set_unusable_password()`` will be called. See _`Creating users` for example usage. @@ -220,7 +234,7 @@ the setting and checking of these values behind the scenes. Previous Django versions, such as 0.90, used simple MD5 hashes without password salts. For backwards compatibility, those are still supported; they'll be -converted automatically to the new style the first time ``check_password()`` +converted automatically to the new style the first time ``User.check_password()`` works correctly for a given user. Anonymous users @@ -422,7 +436,10 @@ template context variables: * ``next``: The URL to redirect to after successful login. This may contain a query string, too. * ``site_name``: The name of the current ``Site``, according to the - ``SITE_ID`` setting. See the `site framework docs`_. + ``SITE_ID`` setting. If you're using the Django development version and + you don't have the site framework installed, this will be set to the + value of ``request.META['SERVER_NAME']``. For more on sites, see the + `site framework docs`_. If you'd prefer not to call the template ``registration/login.html``, you can pass the ``template_name`` parameter via the extra arguments to the view in @@ -661,8 +678,6 @@ Example in Python 2.4 syntax:: The permission_required decorator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**New in Django development version** - It's a relatively common task to check whether a user has a particular permission. For that reason, Django provides a shortcut for that case: the ``permission_required()`` decorator. Using this decorator, the earlier example diff --git a/docs/cache.txt b/docs/cache.txt index e245e100e7..d13352b025 100644 --- a/docs/cache.txt +++ b/docs/cache.txt @@ -543,7 +543,7 @@ Order of MIDDLEWARE_CLASSES If you use ``CacheMiddleware``, it's important to put it in the right place within the ``MIDDLEWARE_CLASSES`` setting, because the cache middleware needs to know which headers by which to vary the cache storage. Middleware always -adds something the ``Vary`` response header when it can. +adds something to the ``Vary`` response header when it can. Put the ``CacheMiddleware`` after any middlewares that might add something to the ``Vary`` header. The following middlewares do so: diff --git a/docs/contributing.txt b/docs/contributing.txt index b3c7efa2f7..b0df62fe99 100644 --- a/docs/contributing.txt +++ b/docs/contributing.txt @@ -67,6 +67,13 @@ particular: likely to get lost. If a particular ticket is controversial, please move discussion to `django-developers`_. + * **Don't** post to django-developers just to announce that you have filed + a bug report. All the tickets are mailed to another list + (`django-updates`_), which is tracked by developers and triagers, so we + see them as they are filed. + +.. _django-updates: http://groups.google.com/group/django-updates + Reporting security issues ========================= @@ -279,6 +286,22 @@ Please follow these coding standards when writing code for inclusion in Django: * Mark all strings for internationalization; see the `i18n documentation`_ for details. + * In docstrings, use "action words" such as:: + + def foo(): + """ + Calculates something and returns the result. + """ + pass + + Here's an example of what not to do:: + + def foo(): + """ + Calculate something and return the result. + """ + pass + * Please don't put your name in the code you contribute. Our policy is to keep contributors' names in the ``AUTHORS`` file distributed with Django -- not scattered throughout the codebase itself. Feel free to include a @@ -324,14 +347,14 @@ Model style Do this:: class Person(models.Model): - first_name = models.CharField(maxlength=20) - last_name = models.CharField(maxlength=40) + first_name = models.CharField(max_length=20) + last_name = models.CharField(max_length=40) Don't do this:: class Person(models.Model): - FirstName = models.CharField(maxlength=20) - Last_Name = models.CharField(maxlength=40) + FirstName = models.CharField(max_length=20) + Last_Name = models.CharField(max_length=40) * The ``class Meta`` should appear *after* the fields are defined, with a single blank line separating the fields and the class definition. @@ -339,8 +362,8 @@ Model style Do this:: class Person(models.Model): - first_name = models.CharField(maxlength=20) - last_name = models.CharField(maxlength=40) + first_name = models.CharField(max_length=20) + last_name = models.CharField(max_length=40) class Meta: verbose_name_plural = 'people' @@ -348,8 +371,8 @@ Model style Don't do this:: class Person(models.Model): - first_name = models.CharField(maxlength=20) - last_name = models.CharField(maxlength=40) + first_name = models.CharField(max_length=20) + last_name = models.CharField(max_length=40) class Meta: verbose_name_plural = 'people' @@ -359,8 +382,8 @@ Model style class Meta: verbose_name_plural = 'people' - first_name = models.CharField(maxlength=20) - last_name = models.CharField(maxlength=40) + first_name = models.CharField(max_length=20) + last_name = models.CharField(max_length=40) * The order of model inner classes and standard methods should be as follows (noting that these are not all required): @@ -368,6 +391,7 @@ Model style * All database fields * ``class Meta`` * ``class Admin`` + * ``def __unicode__()`` * ``def __str__()`` * ``def save()`` * ``def get_absolute_url()`` @@ -393,11 +417,11 @@ Guidelines for ReST files These guidelines regulate the format of our ReST documentation: - * In section titles, capitalize only initial words and proper nouns. + * In section titles, capitalize only initial words and proper nouns. - * Wrap the documentation at 80 characters wide, unless a code example - is significantly less readable when split over two lines, or for another - good reason. + * Wrap the documentation at 80 characters wide, unless a code example + is significantly less readable when split over two lines, or for another + good reason. Commonly used terms ------------------- @@ -405,41 +429,41 @@ Commonly used terms Here are some style guidelines on commonly used terms throughout the documentation: - * **Django** -- when referring to the framework, capitalize Django. It is - lowercase only in Python code and in the djangoproject.com logo. + * **Django** -- when referring to the framework, capitalize Django. It is + lowercase only in Python code and in the djangoproject.com logo. - * **e-mail** -- it has a hyphen. + * **e-mail** -- it has a hyphen. - * **MySQL** + * **MySQL** - * **PostgreSQL** + * **PostgreSQL** - * **Python** -- when referring to the language, capitalize Python. + * **Python** -- when referring to the language, capitalize Python. - * **realize**, **customize**, **initialize**, etc. -- use the American - "ize" suffix, not "ise." + * **realize**, **customize**, **initialize**, etc. -- use the American + "ize" suffix, not "ise." - * **SQLite** + * **SQLite** - * **subclass** -- it's a single word without a hyphen, both as a verb - ("subclass that model") and as a noun ("create a subclass"). + * **subclass** -- it's a single word without a hyphen, both as a verb + ("subclass that model") and as a noun ("create a subclass"). - * **Web**, **World Wide Web**, **the Web** -- note Web is always - capitalized when referring to the World Wide Web. + * **Web**, **World Wide Web**, **the Web** -- note Web is always + capitalized when referring to the World Wide Web. * **Web site** -- use two words, with Web capitalized. Django-specific terminology --------------------------- - * **model** -- it's not capitalized. + * **model** -- it's not capitalized. - * **template** -- it's not capitalized. + * **template** -- it's not capitalized. - * **URLconf** -- use three capitalized letters, with no space before - "conf." + * **URLconf** -- use three capitalized letters, with no space before + "conf." - * **view** -- it's not capitalized. + * **view** -- it's not capitalized. Committing code =============== @@ -528,11 +552,9 @@ To run the tests, ``cd`` to the ``tests/`` directory and type:: ./runtests.py --settings=path.to.django.settings Yes, the unit tests need a settings module, but only for database connection -info -- the ``DATABASE_NAME`` (required, but will be ignored), -``DATABASE_ENGINE``, ``DATABASE_USER`` and ``DATABASE_PASSWORD`` settings. You -will also need a ``ROOT_URLCONF`` setting (its value is ignored; it just needs -to be present) and a ``SITE_ID`` setting (any integer value will do) in order -for all the tests to pass. +info, with the ``DATABASE_ENGINE`` setting. You will also need a ``ROOT_URLCONF`` +setting (its value is ignored; it just needs to be present) and a ``SITE_ID`` +setting (any non-zero integer value will do) in order for all the tests to pass. The unit tests will not touch your existing databases; they create a new database, called ``django_test_db``, which is deleted when the tests are diff --git a/docs/csrf.txt b/docs/csrf.txt index c12dd1d116..7d79e39502 100644 --- a/docs/csrf.txt +++ b/docs/csrf.txt @@ -41,10 +41,10 @@ CsrfMiddleware does two things: This ensures that only forms that have originated from your web site can be used to POST data back. -It deliberately only targets HTTP POST requests (and the corresponding -POST forms). GET requests ought never to have side effects (if you are -using HTTP GET and POST correctly), and so a CSRF attack with a GET -request will always be harmless. +It deliberately only targets HTTP POST requests (and the corresponding POST +forms). GET requests ought never to have any potentially dangerous side +effects (see `9.1.1 Safe Methods, HTTP 1.1, RFC 2616`_), and so a +CSRF attack with a GET request ought to be harmless. POST requests that are not accompanied by a session cookie are not protected, but they do not need to be protected, since the 'attacking' web site @@ -54,6 +54,8 @@ The Content-Type is checked before modifying the response, and only pages that are served as 'text/html' or 'application/xml+xhtml' are modified. +.. _9.1.1 Safe Methods, HTTP 1.1, RFC 2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html + Limitations =========== diff --git a/docs/databases.txt b/docs/databases.txt index b73f39843c..ed0cb61bc3 100644 --- a/docs/databases.txt +++ b/docs/databases.txt @@ -124,7 +124,7 @@ Several other MySQLdb connection options may be useful, such as ``ssl``, ``use_unicode``, ``init_command``, and ``sql_mode``. Consult the `MySQLdb documentation`_ for more details. -.. _settings documentation: http://www.djangoproject.com/documentation/settings/#database-engine +.. _settings documentation: ../settings/#database-engine .. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html .. _MySQLdb documentation: http://mysql-python.sourceforge.net/ diff --git a/docs/databrowse.txt b/docs/databrowse.txt index 9c03e7e4ea..81e9e8e83b 100644 --- a/docs/databrowse.txt +++ b/docs/databrowse.txt @@ -35,6 +35,7 @@ How to use Databrowse 2. Register a number of models with the Databrowse site:: from django.contrib import databrowse + from myapp.models import SomeModel, SomeOtherModel databrowse.site.register(SomeModel) databrowse.site.register(SomeOtherModel) diff --git a/docs/db-api.txt b/docs/db-api.txt index a4b920fb33..766a6ae519 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -12,27 +12,27 @@ Throughout this reference, we'll refer to the following models, which comprise a weblog application:: class Blog(models.Model): - name = models.CharField(maxlength=100) + name = models.CharField(max_length=100) tagline = models.TextField() - def __str__(self): + def __unicode__(self): return self.name class Author(models.Model): - name = models.CharField(maxlength=50) - email = models.URLField() + name = models.CharField(max_length=50) + email = models.EmailField() - def __str__(self): + def __unicode__(self): return self.name class Entry(models.Model): blog = models.ForeignKey(Blog) - headline = models.CharField(maxlength=255) + headline = models.CharField(max_length=255) body_text = models.TextField() pub_date = models.DateTimeField() authors = models.ManyToManyField(Author) - def __str__(self): + def __unicode__(self): return self.headline Creating objects @@ -118,6 +118,79 @@ happens. Explicitly specifying auto-primary-key values is mostly useful for bulk-saving objects, when you're confident you won't have primary-key collision. +What happens when you save? +--------------------------- + +When you save an object, Django performs the following steps: + + 1. **Emit a ``pre_save`` signal.** This provides a notification that + an object is about to be saved. You can register a listener that + will be invoked whenever this signal is emitted. (These signals are + not yet documented.) + + 2. **Pre-process the data.** Each field on the object is asked to + perform any automated data modification that the field may need + to perform. + + Most fields do *no* pre-processing -- the field data is kept as-is. + Pre-processing is only used on fields that have special behavior. + For example, if your model has a ``DateField`` with ``auto_now=True``, + the pre-save phase will alter the data in the object to ensure that + the date field contains the current date stamp. (Our documentation + doesn't yet include a list of all the fields with this "special + behavior.") + + 3. **Prepare the data for the database.** Each field is asked to provide + its current value in a data type that can be written to the database. + + Most fields require *no* data preparation. Simple data types, such as + integers and strings, are 'ready to write' as a Python object. However, + more complex data types often require some modification. + + For example, ``DateFields`` use a Python ``datetime`` object to store + data. Databases don't store ``datetime`` objects, so the field value + must be converted into an ISO-compliant date string for insertion + into the database. + + 4. **Insert the data into the database.** The pre-processed, prepared + data is then composed into an SQL statement for insertion into the + database. + + 5. **Emit a ``post_save`` signal.** As with the ``pre_save`` signal, this + is used to provide notification that an object has been successfully + saved. (These signals are not yet documented.) + +Raw Saves +~~~~~~~~~ + +**New in Django development version** + +The pre-processing step (#2 in the previous section) is useful, but it modifies +the data stored in a field. This can cause problems if you're relying upon the +data you provide being used as-is. + +For example, if you're setting up conditions for a test, you'll want the test +conditions to be repeatable. If pre-processing is performed, the data used +to specify test conditions may be modified, changing the conditions for the +test each time the test is run. + +In cases such as this, you need to prevent pre-processing from being performed +when you save an object. To do this, you can invoke a **raw save** by passing +``raw=True`` as an argument to the ``save()`` method:: + + b4.save(raw=True) # Save object, but do no pre-processing + +A raw save skips the usual data pre-processing that is performed during the +save. All other steps in the save (pre-save signal, data preparation, data +insertion, and post-save signal) are performed as normal. + +.. admonition:: When to use a raw save + + Generally speaking, you shouldn't need to use a raw save. Disabling field + pre-processing is an extraordinary measure that should only be required + in extraordinary circumstances, such as setting up reliable test + conditions. + Saving changes to objects ========================= @@ -140,7 +213,7 @@ object of the right type to the field in question:: joe = Author.objects.create(name="Joe") entry.author = joe entry.save() - + Django will complain if you try to assign an object of the wrong type. How Django knows to UPDATE vs. INSERT @@ -336,7 +409,7 @@ For example, this returns the first 5 objects (``LIMIT 5``):: Entry.objects.all()[:5] -This returns the fifth through tenth objects (``OFFSET 5 LIMIT 5``):: +This returns the sixth through tenth objects (``OFFSET 5 LIMIT 5``):: Entry.objects.all()[5:10] @@ -1430,7 +1503,7 @@ precede the definition of any keyword arguments. For example:: See the `OR lookups examples page`_ for more examples. -.. _OR lookups examples page: http://www.djangoproject.com/documentation/models/or_lookups/ +.. _OR lookups examples page: ../models/or_lookups/ Related objects =============== @@ -1733,8 +1806,8 @@ following model:: ('F', 'Female'), ) class Person(models.Model): - name = models.CharField(maxlength=20) - gender = models.CharField(maxlength=1, choices=GENDER_CHOICES) + name = models.CharField(max_length=20) + gender = models.CharField(max_length=1, choices=GENDER_CHOICES) ...each ``Person`` instance will have a ``get_gender_display()`` method. Example:: @@ -1761,7 +1834,7 @@ Note that in the case of identical date values, these methods will use the ID as a fallback check. This guarantees that no records are skipped or duplicated. For a full example, see the `lookup API sample model`_. -.. _lookup API sample model: http://www.djangoproject.com/documentation/models/lookup/ +.. _lookup API sample model: ../models/lookup/ get_FOO_filename() ------------------ @@ -1818,8 +1891,8 @@ get_object_or_404() One common idiom to use ``get()`` and raise ``Http404`` if the object doesn't exist. This idiom is captured by ``get_object_or_404()``. This function takes a Django model as its first argument and an -arbitrary number of keyword arguments, which it passes to the manager's -``get()`` function. It raises ``Http404`` if the object doesn't +arbitrary number of keyword arguments, which it passes to the default +manager's ``get()`` function. It raises ``Http404`` if the object doesn't exist. For example:: # Get the Entry with a primary key of 3 @@ -1828,7 +1901,7 @@ exist. For example:: When you provide a model to this shortcut function, the default manager is used to execute the underlying ``get()`` query. If you don't want to use the default manager, or if you want to search a list of related objects, -you can provide ``get_object_or_404()`` with a manager object instead. +you can provide ``get_object_or_404()`` with a ``Manager`` object instead. For example:: # Get the author of blog instance e with a name of 'Fred' @@ -1838,6 +1911,14 @@ For example:: # entry with a primary key of 3 e = get_object_or_404(Entry.recent_entries, pk=3) +**New in Django development version:** The first argument to +``get_object_or_404()`` can be a ``QuerySet`` object. This is useful in cases +where you've defined a custom manager method. For example:: + + # Use a QuerySet returned from a 'published' method of a custom manager + # in the search for an entry with primary key of 5 + e = get_object_or_404(Entry.objects.published(), pk=5) + get_list_or_404() ----------------- diff --git a/docs/distributions.txt b/docs/distributions.txt index 4ec265f93c..f9b9cbe9f8 100644 --- a/docs/distributions.txt +++ b/docs/distributions.txt @@ -21,16 +21,17 @@ Linux distributions Debian ------ -A `packaged version of Django`_ is available for `Debian GNU/Linux`_, and can be -installed from either the "testing" or the "unstable" repositories by typing -``apt-get install python-django``. +A `packaged version of Django`_ is available for `Debian GNU/Linux`_. Version +0.95.1 is available in the "stable" repository; Version 0.96 is available in +the "testing" and "unstable" repositories. Regardless of your chosen repository, +you can install Django by typing ``apt-get install python-django``. When you install this package, ``apt`` will recommend installing a database adapter; you should select and install the adapter for whichever database you plan to use with Django. .. _Debian GNU/Linux: http://www.debian.org/ -.. _packaged version of Django: http://packages.debian.org/testing/python/python-django +.. _packaged version of Django: http://packages.debian.org/stable/python/python-django Ubuntu ------ @@ -64,11 +65,24 @@ The `current Gentoo build`_ can be installed by typing ``emerge django``. .. _Gentoo Linux: http://www.gentoo.org/ .. _current Gentoo build: http://packages.gentoo.org/packages/?category=dev-python;name=django +Mac OS X +======== + +MacPorts +-------- + +Django 0.96 can be installed via the `MacPorts`_ system. If you're using Python 2.4, +type ``sudo port install py-django-devel``. For Python 2.5, type ``sudo port +install py25-django-devel``. MacPorts can also be used to install a database, +and the Python interface to your chosen database. + +.. _MacPorts: http://www.macports.org/ + For distributors ================ If you'd like to package Django for distribution, we'd be happy to help out! -Please join the `django-developers mailing list`_ and introduce yourself. +Please join the `django-developers mailing list`_ and introduce yourself. We also encourage all distributors to subscribe to the `django-announce mailing list`_, which is a (very) low-traffic list for announcing new releases of Django diff --git a/docs/django-admin.txt b/docs/django-admin.txt index 75c2738543..aea990c5dc 100644 --- a/docs/django-admin.txt +++ b/docs/django-admin.txt @@ -235,6 +235,7 @@ The ``dumpdata`` command can be used to generate input for ``loaddata``. reset [appname appname ...] --------------------------- + Executes the equivalent of ``sqlreset`` for the given appnames. runfcgi [options] @@ -400,6 +401,19 @@ install them in the database. This includes any apps shipped with Django that might be in ``INSTALLED_APPS`` by default. When you start a new project, run this command to install the default apps. +.. admonition:: Syncdb will not alter existing tables + + ``syncdb`` will only create tables for models which have not yet been + installed. It will *never* issue ``ALTER TABLE`` statements to match + changes made to a model class after installation. Changes to model classes + and database schemas often involve some form of ambiguity and, in those + cases, Django would have to guess at the correct changes to make. There is + a risk that critical data would be lost in the process. + + If you have made changes to a model and wish to alter the database tables + to match, use the ``sql`` command to display the new SQL structure and + compare that to your existing table schema to work out the changes. + If you're installing the ``django.contrib.auth`` application, ``syncdb`` will give you the option of creating a superuser immediately. @@ -413,7 +427,46 @@ test Discover and run tests for all installed models. See `Testing Django applications`_ for more information. -.. _testing django applications: ../testing/ +.. _testing Django applications: ../testing/ + +testserver [fixture fixture ...] +-------------------------------- + +**New in Django development version** + +Runs a Django development server (as in ``runserver``) using data from the +given fixture(s). + +For example, this command:: + + django-admin.py testserver mydata.json + +...would perform the following steps: + + 1. Create a test database, as described in `testing Django applications`_. + 2. Populate the test database with fixture data from the given fixtures. + (For more on fixtures, see the documentation for ``loaddata`` above.) + 3. Runs the Django development server (as in ``runserver``), pointed at + this newly created test database instead of your production database. + +This is useful in a number of ways: + + * When you're writing `unit tests`_ of how your views act with certain + fixture data, you can use ``testserver`` to interact with the views in + a Web browser, manually. + + * Let's say you're developing your Django application and have a "pristine" + copy of a database that you'd like to interact with. You can dump your + database to a fixture (using the ``dumpdata`` command, explained above), + then use ``testserver`` to run your Web application with that data. With + this arrangement, you have the flexibility of messing up your data + in any way, knowing that whatever data changes you're making are only + being made to a test database. + +Note that this server can only run on the default port on localhost; it does +not yet accept a ``host`` or ``port`` parameter. + +.. _unit tests: ../testing/ validate -------- diff --git a/docs/email.txt b/docs/email.txt index 50dafaf8df..97bdec0037 100644 --- a/docs/email.txt +++ b/docs/email.txt @@ -314,7 +314,7 @@ To send a text and HTML combination, you could write:: subject, from_email, to = 'hello', 'from@example.com', 'to@example.com' text_content = 'This is an important message.' - html_content = '

This is an important message.' + html_content = '

This is an important message.

' msg = EmailMultiAlternatives(subject, text_content, from_email, to) msg.attach_alternative(html_content, "text/html") msg.send() diff --git a/docs/faq.txt b/docs/faq.txt index 67ed8a49a5..844ea77809 100644 --- a/docs/faq.txt +++ b/docs/faq.txt @@ -42,7 +42,10 @@ Listen to his music. You'll like it. Django is pronounced **JANG**-oh. Rhymes with FANG-oh. The "D" is silent. +We've also recorded an `audio clip of the pronunciation`_. + .. _Django Reinhardt: http://en.wikipedia.org/wiki/Django_Reinhardt +.. _audio clip of the pronunciation: http://red-bean.com/~adrian/django_pronunciation.mp3 Is Django stable? ----------------- diff --git a/docs/fastcgi.txt b/docs/fastcgi.txt index 81888bba76..dff1689905 100644 --- a/docs/fastcgi.txt +++ b/docs/fastcgi.txt @@ -93,7 +93,7 @@ protocol by using the ``protocol=`` option with ``./manage.py runfcgi`` -- where ```` may be one of: ``fcgi`` (the default), ``scgi`` or ``ajp``. For example:: - ./manage.py runfcgi --protocol=scgi + ./manage.py runfcgi protocol=scgi .. _flup: http://www.saddi.com/software/flup/ .. _fastcgi: http://www.fastcgi.com/ diff --git a/docs/forms.txt b/docs/forms.txt index f6cb55a3f6..18d322a8eb 100644 --- a/docs/forms.txt +++ b/docs/forms.txt @@ -37,17 +37,17 @@ this document, we'll be working with the following model, a "place" object:: ) class Place(models.Model): - name = models.CharField(maxlength=100) - address = models.CharField(maxlength=100, blank=True) - city = models.CharField(maxlength=50, blank=True) + name = models.CharField(max_length=100) + address = models.CharField(max_length=100, blank=True) + city = models.CharField(max_length=50, blank=True) state = models.USStateField() - zip_code = models.CharField(maxlength=5, blank=True) + zip_code = models.CharField(max_length=5, blank=True) place_type = models.IntegerField(choices=PLACE_TYPES) class Admin: pass - def __str__(self): + def __unicode__(self): return self.name Defining the above class is enough to create an admin interface to a ``Place``, @@ -388,7 +388,7 @@ for a "contact" form on a website:: def __init__(self): self.fields = ( forms.EmailField(field_name="from", is_required=True), - forms.TextField(field_name="subject", length=30, maxlength=200, is_required=True), + forms.TextField(field_name="subject", length=30, max_length=200, is_required=True), forms.SelectField(field_name="urgency", choices=urgency_choices), forms.LargeTextField(field_name="contents", is_required=True), ) diff --git a/docs/generic_views.txt b/docs/generic_views.txt index 2b80348903..0601aead11 100644 --- a/docs/generic_views.txt +++ b/docs/generic_views.txt @@ -40,7 +40,7 @@ simple weblog app that drives the blog on djangoproject.com:: } urlpatterns = patterns('django.views.generic.date_based', - (r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/(?P[-\w]+)/$', 'object_detail', dict(info_dict, slug_field='slug')), + (r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/(?P[-\w]+)/$', 'object_detail', info_dict), (r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/$', 'archive_day', info_dict), (r'^(?P\d{4})/(?P[a-z]{3})/$', 'archive_month', info_dict), (r'^(?P\d{4})/$', 'archive_year', info_dict), @@ -603,7 +603,7 @@ future, the view will throw a 404 error by default, unless you set Otherwise, ``slug`` should be the slug of the given object, and ``slug_field`` should be the name of the slug field in the ``QuerySet``'s - model. + model. By default, ``slug_field`` is ``'slug'``. **Optional arguments:** @@ -804,7 +804,7 @@ A page representing an individual object. Otherwise, ``slug`` should be the slug of the given object, and ``slug_field`` should be the name of the slug field in the ``QuerySet``'s - model. + model. By default, ``slug_field`` is ``'slug'``. **Optional arguments:** @@ -948,7 +948,7 @@ object. This uses the automatic manipulators that come with Django models. Otherwise, ``slug`` should be the slug of the given object, and ``slug_field`` should be the name of the slug field in the ``QuerySet``'s - model. + model. By default, ``slug_field`` is ``'slug'``. **Optional arguments:** @@ -1033,7 +1033,7 @@ contain a form that POSTs to the same URL. Otherwise, ``slug`` should be the slug of the given object, and ``slug_field`` should be the name of the slug field in the ``QuerySet``'s - model. + model. By default, ``slug_field`` is ``'slug'``. * ``post_delete_redirect``: A URL to which the view will redirect after deleting the object. diff --git a/docs/i18n.txt b/docs/i18n.txt index 27abadacc9..38252edeb1 100644 --- a/docs/i18n.txt +++ b/docs/i18n.txt @@ -68,23 +68,41 @@ In Python code Standard translation ~~~~~~~~~~~~~~~~~~~~ -Specify a translation string by using the function ``_()``. (Yes, the name of -the function is the "underscore" character.) This function is available -globally in any Python module; you don't have to import it. +Specify a translation string by using the function ``ugettext()``. It's +convention to import this as a shorter alias, ``_``, to save typing. + +.. note:: + Python's standard library ``gettext`` module installs ``_()`` into the + global namespace, as an alias for ``gettext()``. In Django, we have chosen + not to follow this practice, for a couple of reasons: + + 1. For international character set (Unicode) support, ``ugettext()`` is + more useful than ``gettext()``. Sometimes, you should be using + ``ugettext_lazy()`` as the default translation method for a particular + file. Without ``_()`` in the global namespace, the developer has to + think about which is the most appropriate translation function. + + 2. The underscore character (``_``) is used to represent "the previous + result" in Python's interactive shell and doctest tests. Installing a + global ``_()`` function causes interference. Explicitly importing + ``ugettext()`` as ``_()`` avoids this problem. In this example, the text ``"Welcome to my site."`` is marked as a translation string:: + from django.utils.translation import ugettext as _ + def my_view(request): output = _("Welcome to my site.") return HttpResponse(output) -The function ``django.utils.translation.gettext()`` is identical to ``_()``. -This example is identical to the previous one:: +Obviously, you could code this without using the alias. This example is +identical to the previous one:: + + from django.utils.translation import ugettext - from django.utils.translation import gettext def my_view(request): - output = gettext("Welcome to my site.") + output = ugettext("Welcome to my site.") return HttpResponse(output) Translation works on computed values. This example is identical to the previous @@ -107,7 +125,7 @@ examples, is that Django's translation-string-detecting utility, ``make-messages.py``, won't be able to find these strings. More on ``make-messages`` later.) -The strings you pass to ``_()`` or ``gettext()`` can take placeholders, +The strings you pass to ``_()`` or ``ugettext()`` can take placeholders, specified with Python's standard named-string interpolation syntax. Example:: def my_view(request, n): @@ -120,14 +138,14 @@ while a Spanish translation may be ``"Me llamo Adrian."`` -- with the placeholder (the name) placed after the translated text instead of before it. For this reason, you should use named-string interpolation (e.g., ``%(name)s``) -instead of positional interpolation (e.g., ``%s`` or ``%d``). If you used -positional interpolation, translations wouldn't be able to reorder placeholder -text. +instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you +have more than a single parameter. If you used positional interpolation, +translations wouldn't be able to reorder placeholder text. Marking strings as no-op ~~~~~~~~~~~~~~~~~~~~~~~~ -Use the function ``django.utils.translation.gettext_noop()`` to mark a string +Use the function ``django.utils.translation.ugettext_noop()`` to mark a string as a translation string without translating it. The string is later translated from a variable. @@ -139,35 +157,35 @@ as when the string is presented to the user. Lazy translation ~~~~~~~~~~~~~~~~ -Use the function ``django.utils.translation.gettext_lazy()`` to translate +Use the function ``django.utils.translation.ugettext_lazy()`` to translate strings lazily -- when the value is accessed rather than when the -``gettext_lazy()`` function is called. +``ugettext_lazy()`` function is called. For example, to translate a model's ``help_text``, do the following:: - from django.utils.translation import gettext_lazy + from django.utils.translation import ugettext_lazy class MyThing(models.Model): - name = models.CharField(help_text=gettext_lazy('This is the help text')) + name = models.CharField(help_text=ugettext_lazy('This is the help text')) -In this example, ``gettext_lazy()`` stores a lazy reference to the string -- +In this example, ``ugettext_lazy()`` stores a lazy reference to the string -- not the actual translation. The translation itself will be done when the string is used in a string context, such as template rendering on the Django admin site. -If you don't like the verbose name ``gettext_lazy``, you can just alias it as +If you don't like the verbose name ``ugettext_lazy``, you can just alias it as ``_`` (underscore), like so:: - from django.utils.translation import gettext_lazy as _ + from django.utils.translation import ugettext_lazy as _ class MyThing(models.Model): name = models.CharField(help_text=_('This is the help text')) -Always use lazy translations in `Django models`_. And it's a good idea to add +Always use lazy translations in `Django models`_. It's a good idea to add translations for the field names and table names, too. This means writing explicit ``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class, though:: - from django.utils.translation import gettext_lazy as _ + from django.utils.translation import ugettext_lazy as _ class MyThing(models.Model): name = models.CharField(_('name'), help_text=_('This is the help text')) @@ -180,24 +198,24 @@ class, though:: Pluralization ~~~~~~~~~~~~~ -Use the function ``django.utils.translation.ngettext()`` to specify pluralized +Use the function ``django.utils.translation.ungettext()`` to specify pluralized messages. Example:: - from django.utils.translation import ngettext + from django.utils.translation import ungettext def hello_world(request, count): - page = ngettext('there is %(count)d object', 'there are %(count)d objects', count) % { + page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % { 'count': count, } return HttpResponse(page) -``ngettext`` takes three arguments: the singular translation string, the plural +``ungettext`` takes three arguments: the singular translation string, the plural translation string and the number of objects (which is passed to the translation languages as the ``count`` variable). In template code ---------------- -Using translations in `Django templates`_ uses two template tags and a slightly +Translations in `Django templates`_ uses two template tags and a slightly different syntax than in Python code. To give your template access to these tags, put ``{% load i18n %}`` toward the top of your template. @@ -243,9 +261,9 @@ To pluralize, specify both the singular and plural forms with the {% endblocktrans %} Internally, all block and inline translations use the appropriate -``gettext`` / ``ngettext`` call. +``ugettext`` / ``ungettext`` call. -Each ``RequestContext`` has access to two translation-specific variables: +Each ``RequestContext`` has access to three translation-specific variables: * ``LANGUAGES`` is a list of tuples in which the first element is the language code and the second is the language name (in that language). @@ -276,6 +294,71 @@ string, so they don't need to be aware of translations. .. _Django templates: ../templates_python/ +Working with lazy translation objects +===================================== + +Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models +and utility functions is a common operation. When you're working with these +objects elsewhere in your code, you should ensure that you don't accidentally +convert them to strings, because they should be converted as late as possible +(so that the correct locale is in effect). This necessitates the use of a +couple of helper functions. + +Joining strings: string_concat() +-------------------------------- + +Standard Python string joins (``''.join([...])``) will not work on lists +containing lazy translation objects. Instead, you can use +``django.utils.translation.string_concat()``, which creates a lazy object that +concatenates its contents *and* converts them to strings only when the result +is included in a string. For example:: + + from django.utils.translation import string_concat + ... + name = ugettext_lazy(u'John Lennon') + instrument = ugettext_lazy(u'guitar') + result = string_concat([name, ': ', instrument]) + +In this case, the lazy translations in ``result`` will only be converted to +strings when ``result`` itself is used in a string (usually at template +rendering time). + +The allow_lazy() decorator +-------------------------- + +Django offers many utility functions (particularly in ``django.utils``) that +take a string as their first argument and do something to that string. These +functions are used by template filters as well as directly in other code. + +If you write your own similar functions and deal with translations, you'll +face the problem of what to do when the first argument is a lazy translation +object. You don't want to convert it to a string immediately, because you might +be using this function outside of a view (and hence the current thread's locale +setting will not be correct). + +For cases like this, use the ``django.utils.functional.allow_lazy()`` +decorator. It modifies the function so that *if* it's called with a lazy +translation as the first argument, the function evaluation is delayed until it +needs to be converted to a string. + +For example:: + + from django.utils.functional import allow_lazy + + def fancy_utility_function(s, ...): + # Do some conversion on string 's' + ... + fancy_utility_function = allow_lazy(fancy_utility_function, unicode) + +The ``allow_lazy()`` decorator takes, in addition to the function to decorate, +a number of extra arguments (``*args``) specifying the type(s) that the +original function can return. Usually, it's enough to include ``unicode`` here +and ensure that your function returns only Unicode strings. + +Using this decorator means you can write your function and assume that the +input is a proper string, then add support for lazy translation objects at the +end. + How to create language files ============================ @@ -487,26 +570,26 @@ Notes: * If you define a custom ``LANGUAGES`` setting, as explained in the previous bullet, it's OK to mark the languages as translation strings - -- but use a "dummy" ``gettext()`` function, not the one in + -- but use a "dummy" ``ugettext()`` function, not the one in ``django.utils.translation``. You should *never* import ``django.utils.translation`` from within your settings file, because that module in itself depends on the settings, and that would cause a circular import. - The solution is to use a "dummy" ``gettext()`` function. Here's a sample + The solution is to use a "dummy" ``ugettext()`` function. Here's a sample settings file:: - gettext = lambda s: s + ugettext = lambda s: s LANGUAGES = ( - ('de', gettext('German')), - ('en', gettext('English')), + ('de', ugettext('German')), + ('en', ugettext('English')), ) With this arrangement, ``make-messages.py`` will still find and mark these strings for translation, but the translation won't happen at runtime -- so you'll have to remember to wrap the languages in the *real* - ``gettext()`` in any code that uses ``LANGUAGES`` at runtime. + ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime. * The ``LocaleMiddleware`` can only select languages for which there is a Django-provided base translation. If you want to provide translations @@ -712,23 +795,23 @@ interface to access it:: document.write(gettext('this is to be translated')); -There even is a ``ngettext`` interface and a string interpolation function:: +There even is a ``ungettext`` interface and a string interpolation function:: d = { count: 10 }; - s = interpolate(ngettext('this is %(count)s object', 'this are %(count)s objects', d.count), d); + s = interpolate(ungettext('this is %(count)s object', 'this are %(count)s objects', d.count), d); The ``interpolate`` function supports both positional interpolation and named interpolation. So the above could have been written as:: - s = interpolate(ngettext('this is %s object', 'this are %s objects', 11), [11]); + s = interpolate(ungettext('this is %s object', 'this are %s objects', 11), [11]); The interpolation syntax is borrowed from Python. You shouldn't go over the top with string interpolation, though: this is still JavaScript, so the code will have to do repeated regular-expression substitutions. This isn't as fast as string interpolation in Python, so keep it to those cases where you really -need it (for example, in conjunction with ``ngettext`` to produce proper +need it (for example, in conjunction with ``ungettext`` to produce proper pluralizations). Creating JavaScript translation catalogs @@ -750,16 +833,13 @@ Specialities of Django translation If you know ``gettext``, you might note these specialities in the way Django does translation: - * The string domain is ``django`` or ``djangojs``. The string domain is used to - differentiate between different programs that store their data in a - common message-file library (usually ``/usr/share/locale/``). The ``django`` - domain is used for python and template translation strings and is loaded into - the global translation catalogs. The ``djangojs`` domain is only used for - JavaScript translation catalogs to make sure that those are as small as - possible. - * Django only uses ``gettext`` and ``gettext_noop``. That's because Django - always uses ``DEFAULT_CHARSET`` strings internally. There isn't much use - in using ``ugettext``, because you'll always need to produce utf-8 - anyway. + * The string domain is ``django`` or ``djangojs``. The string domain is + used to differentiate between different programs that store their data + in a common message-file library (usually ``/usr/share/locale/``). The + ``django`` domain is used for python and template translation strings + and is loaded into the global translation catalogs. The ``djangojs`` + domain is only used for JavaScript translation catalogs to make sure + that those are as small as possible. * Django doesn't use ``xgettext`` alone. It uses Python wrappers around ``xgettext`` and ``msgfmt``. That's mostly for convenience. + diff --git a/docs/install.txt b/docs/install.txt index e850e48955..082000149f 100644 --- a/docs/install.txt +++ b/docs/install.txt @@ -48,8 +48,8 @@ Get your database running If you plan to use Django's database API functionality, you'll need to make sure a database server is running. Django works with PostgreSQL_, -MySQL_, Oracle_ and SQLite_ (the latter doesn't require a separate server to -be running). +MySQL_, Oracle_ and SQLite_ (although SQLite doesn't require a separate server +to be running). Additionally, you'll need to make sure your Python database bindings are installed. @@ -109,25 +109,29 @@ Install the Django code ======================= Installation instructions are slightly different depending on whether you're -using the latest official version or the latest development version. +installing a distribution-specific package, downloading the the latest official +release, or fetching the latest development version. -It's easy either way. +It's easy, no matter which way you choose. -Installing the official version -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Installing a distribution-specific package +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 1. Check the `distribution specific notes`_ to see if your - platform/distribution provides official Django packages/installers. - Distribution-provided packages will typically allow for automatic - installation of dependancies and easy upgrade paths. +Check the `distribution specific notes`_ to see if your +platform/distribution provides official Django packages/installers. +Distribution-provided packages will typically allow for automatic +installation of dependancies and easy upgrade paths. - 2. Download the latest release from our `download page`_. +Installing an official release +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 3. Untar the downloaded file (e.g. ``tar xzvf Django-NNN.tar.gz``). + 1. Download the latest release from our `download page`_. - 4. Change into the downloaded directory (e.g. ``cd Django-NNN``). + 2. Untar the downloaded file (e.g. ``tar xzvf Django-NNN.tar.gz``). - 5. Run ``sudo python setup.py install``. + 3. Change into the downloaded directory (e.g. ``cd Django-NNN``). + + 4. Run ``sudo python setup.py install``. The command will install Django in your Python installation's ``site-packages`` directory. diff --git a/docs/man/compile-messages.1 b/docs/man/compile-messages.1 new file mode 100644 index 0000000000..d26a94aca7 --- /dev/null +++ b/docs/man/compile-messages.1 @@ -0,0 +1,40 @@ +.TH "compile-messages.py" "1" "August 2007" "Django Project" "" +.SH "NAME" +compile-messages.py \- Internationalization utility for the Django +web framework +.SH "SYNOPSIS" +.B compile-messages.py \fR[-l ] + +.SH "DESCRIPTION" +A Django-customised wrapper around gettext's \fBmsgfmt\fR command. Generates +binary message catalogs (.mo files) from textual translation descriptions (.po +files). +.sp +The script should be invoked after running +.BI make-messages.py, +in the same directory from which +.BI make-messages.py +was invoked. + +.SH "OPTIONS" +.TP +.I \-l +Compile the message catalogs for a specific locale. If this option is omitted, +all message catalogs are (re-)compiled. + +.SH "SEE ALSO" +The man page for +.BI msgfmt +from the GNU gettext utilities, and the internationalization documentation +for Django: +.sp +.I http://www.djangoproject.com/documentation/i18n/ + +.SH "AUTHORS/CREDITS" +Originally developed at World Online in Lawrence, Kansas, USA. Refer to the +AUTHORS file in the Django distribution for contributors. + +.SH "LICENSE" +New BSD license. For the full license text refer to the LICENSE file in the +Django distribution. + diff --git a/docs/man/daily_cleanup.1 b/docs/man/daily_cleanup.1 new file mode 100644 index 0000000000..9186dd67d6 --- /dev/null +++ b/docs/man/daily_cleanup.1 @@ -0,0 +1,34 @@ +.TH "daily_cleanup.py" "1" "August 2007" "Django Project" "" +.SH "NAME" +daily_cleanup.py \- Database clean-up for the Django web framework +.SH "SYNOPSIS" +.B daily_cleanup.py + +.SH "DESCRIPTION" +Removes stale session data from a Django database. This means, any session data +which has an expiry date prior to the date the script is run. +.sp +The script can be run manually or can be scheduled to run at regular +intervals as a +.BI cron +job. + +.SH "ENVIRONMENT" +.TP +.I DJANGO_SETTINGS_MODULE +This environment variable defines the settings module to be read. +It should be in Python-import form, e.g. "myproject.settings". + +.SH "SEE ALSO" +The sessions documentation: +.sp +.I http://www.djangoproject.com/documentation/sessions/ + +.SH "AUTHORS/CREDITS" +Originally developed at World Online in Lawrence, Kansas, USA. Refer to the +AUTHORS file in the Django distribution for contributors. + +.SH "LICENSE" +New BSD license. For the full license text refer to the LICENSE file in the +Django distribution. + diff --git a/docs/man/gather_profile_stats.1 b/docs/man/gather_profile_stats.1 new file mode 100644 index 0000000000..5ff13d8e69 --- /dev/null +++ b/docs/man/gather_profile_stats.1 @@ -0,0 +1,26 @@ +.TH "gather_profile_stats.py" "1" "August 2007" "Django Project" "" +.SH "NAME" +gather_profile_stats.py \- Performance analysis tool for the Django web +framework +.SH "SYNOPSIS" +.B python gather_profile_stats.py +.I + +.SH "DESCRIPTION" +This utility script aggregates profiling logs generated using Python's +hotshot profiler. The sole command-line argument is the full path to the +directory containing the profiling logfiles. + +.SH "SEE ALSO" +Discussion of profiling Django applications on the Django project's wiki: +.sp +.I http://www.djangoproject.com/wiki/ProfilingDjango + +.SH "AUTHORS/CREDITS" +Originally developed at World Online in Lawrence, Kansas, USA. Refer to the +AUTHORS file in the Django distribution for contributors. + +.SH "LICENSE" +New BSD license. For the full license text refer to the LICENSE file in the +Django distribution. + diff --git a/docs/man/make-messages.1 b/docs/man/make-messages.1 new file mode 100644 index 0000000000..b8c83dcff5 --- /dev/null +++ b/docs/man/make-messages.1 @@ -0,0 +1,62 @@ +.TH "make-messages.py" "1" "August 2007" "Django Project" "" +.SH "NAME" +make-messages.py \- Internationalization utility for the Django +web framework +.SH "SYNOPSIS" +.B make-messages.py\fR [\-a] [\-v] [\-l ] [\-d ] + +.SH "DESCRIPTION" +This script creates or updates one or more message files for a Django app, +a Django project or the Django framework itself. It should be run from one +of three places: the root directory of a Django app; the root directory +of a Django project; or the root django directory (the one in your PYTHONPATH, +not the root of a Subversion checkout). +.sp +The script will run over the source tree of an application, project or Django +itself (depending on where it is invoked), pulling out all strings marked for +translation and creating or updating a standard PO-format message file for the +specified language. Refer to Django's internationalization documentation for +details of where this file is created. +.sp +The \fI\-a\fR and \fI\-l\fR options are used to control whether message +catalogs are created for all locales, or just a single one. + +.SH "OPTIONS" +.TP +.I \-a +Run make-messages for all locales specified in the Django settings file. Cannot +be used in conjuntion with \fI\-l\fR. +.TP +.I \-d +Specifies the translation domain to use. Valid domains are \fIdjango\fR or +\fIdjangojs\fR, depending on whether you wish to generate translation strings +for the Python or JavaScript components of your app, your project or the +framework itself. The default domain is \fIdjango\fR. +.TP +.I \-l +Extract messages for a particular locale. +.TP +.I \-v +Run verbosely. + +.SH "ENVIRONMENT" +.TP +.I DJANGO_SETTINGS_MODULE +This environment variable defines the settings module to be read. +It should be in Python-import form, e.g. "myproject.settings". + +.SH "SEE ALSO" +The Django internationalization documentation: +.sp +.I http://www.djangoproject.com/documentation/i18n/ +.sp +The PO file format is documented in the GNU gettext documentation. + +.SH "AUTHORS/CREDITS" +Originally developed at World Online in Lawrence, Kansas, USA. Refer to the +AUTHORS file in the Django distribution for contributors. + +.SH "LICENSE" +New BSD license. For the full license text refer to the LICENSE file in the +Django distribution. + diff --git a/docs/middleware.txt b/docs/middleware.txt index 0d533443d3..63ba8c6999 100644 --- a/docs/middleware.txt +++ b/docs/middleware.txt @@ -91,6 +91,12 @@ django.middleware.gzip.GZipMiddleware Compresses content for browsers that understand gzip compression (all modern browsers). +It is suggested to place this first in the middleware list, so that the +compression of the response content is the last thing that happens. Will not +compress content bodies less than 200 bytes long, when the response code is +something other than 200, Javascript files (for IE compatibitility), or +responses that have the ``Content-Encoding`` header already specified. + django.middleware.http.ConditionalGetMiddleware ----------------------------------------------- @@ -116,6 +122,14 @@ not use this middleware. Anybody can spoof the value of ``HTTP_X_FORWARDED_FOR``, that means anybody can "fake" their IP address. Only use this when you can absolutely trust the value of ``HTTP_X_FORWARDED_FOR``. +django.middleware.locale.LocaleMiddleware +----------------------------------------- + +Enables language selection based on data from the request. It customizes content +for each user. See the `internationalization documentation`_. + +.. _`internationalization documentation`: ../i18n/ + django.contrib.sessions.middleware.SessionMiddleware ---------------------------------------------------- diff --git a/docs/model-api.txt b/docs/model-api.txt index 22ff7445b5..0f872c3097 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -22,7 +22,7 @@ A companion to this document is the `official repository of model examples`_. ``tests/modeltests`` directory.) .. _Database API reference: ../db-api/ -.. _official repository of model examples: http://www.djangoproject.com/documentation/models/ +.. _official repository of model examples: ../models/ Quick example ============= @@ -33,8 +33,8 @@ This example model defines a ``Person``, which has a ``first_name`` and from django.db import models class Person(models.Model): - first_name = models.CharField(maxlength=30) - last_name = models.CharField(maxlength=30) + first_name = models.CharField(max_length=30) + last_name = models.CharField(max_length=30) ``first_name`` and ``last_name`` are *fields* of the model. Each field is specified as a class attribute, and each attribute maps to a database column. @@ -69,13 +69,13 @@ attributes. Example:: class Musician(models.Model): - first_name = models.CharField(maxlength=50) - last_name = models.CharField(maxlength=50) - instrument = models.CharField(maxlength=100) + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) + instrument = models.CharField(max_length=100) class Album(models.Model): artist = models.ForeignKey(Musician) - name = models.CharField(maxlength=100) + name = models.CharField(max_length=100) release_date = models.DateField() num_stars = models.IntegerField() @@ -142,14 +142,18 @@ For large amounts of text, use ``TextField``. The admin represents this as an ```` (a single-line input). -``CharField`` has an extra required argument, ``maxlength``, the maximum length -(in characters) of the field. The maxlength is enforced at the database level +``CharField`` has an extra required argument, ``max_length``, the maximum length +(in characters) of the field. The max_length is enforced at the database level and in Django's validation. +Django veterans: Note that the argument is now called ``max_length`` to +provide consistency throughout Django. There is full legacy support for +the old ``maxlength`` argument, but ``max_length`` is prefered. + ``CommaSeparatedIntegerField`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A field of integers separated by commas. As in ``CharField``, the ``maxlength`` +A field of integers separated by commas. As in ``CharField``, the ``max_length`` argument is required. ``DateField`` @@ -217,7 +221,7 @@ The admin represents this as an ```` (a single-line input). ~~~~~~~~~~~~~~ A ``CharField`` that checks that the value is a valid e-mail address. -This doesn't accept ``maxlength``; its ``maxlength`` is automatically set to +This doesn't accept ``max_length``; its ``max_length`` is automatically set to 75. ``FileField`` @@ -400,7 +404,7 @@ Like a ``PositiveIntegerField``, but only allows values under a certain containing only letters, numbers, underscores or hyphens. They're generally used in URLs. -Like a CharField, you can specify ``maxlength``. If ``maxlength`` is +Like a CharField, you can specify ``max_length``. If ``max_length`` is not specified, Django will use a default length of 50. Implies ``db_index=True``. @@ -411,7 +415,8 @@ form:: models.SlugField(prepopulate_from=("pre_name", "name")) -``prepopulate_from`` doesn't accept DateTimeFields. +``prepopulate_from`` doesn't accept DateTimeFields, ForeignKeys nor +ManyToManyFields. The admin represents ``SlugField`` as an ```` (a single-line input). @@ -447,9 +452,9 @@ and doesn't give a 404 response). The admin represents this as an ```` (a single-line input). -``URLField`` takes an optional argument, ``maxlength``, the maximum length (in -characters) of the field. The maxlength is enforced at the database level and -in Django's validation. If you don't specify ``maxlength``, a default of 200 +``URLField`` takes an optional argument, ``max_length``, the maximum length (in +characters) of the field. The maximum length is enforced at the database level and +in Django's validation. If you don't specify ``max_length``, a default of 200 is used. ``USStateField`` @@ -536,7 +541,7 @@ The choices list can be defined either as part of your model class:: ('M', 'Male'), ('F', 'Female'), ) - gender = models.CharField(maxlength=1, choices=GENDER_CHOICES) + gender = models.CharField(max_length=1, choices=GENDER_CHOICES) or outside your model class altogether:: @@ -545,7 +550,7 @@ or outside your model class altogether:: ('F', 'Female'), ) class Foo(models.Model): - gender = models.CharField(maxlength=1, choices=GENDER_CHOICES) + gender = models.CharField(max_length=1, choices=GENDER_CHOICES) For each model field that has ``choices`` set, Django will add a method to retrieve the human-readable name for the field's current value. See @@ -620,6 +625,12 @@ Extra "help" text to be displayed under the field on the object's admin form. It's useful for documentation even if your object doesn't have an admin form. +Note that this value is *not* HTML-escaped when it's displayed in the admin +interface. This lets you include HTML in ``help_text`` if you so desire. For +example:: + + help_text="Please use the following format: YYYY-MM-DD." + ``primary_key`` ~~~~~~~~~~~~~~~ @@ -698,11 +709,11 @@ it using the field's attribute name, converting underscores to spaces. In this example, the verbose name is ``"Person's first name"``:: - first_name = models.CharField("Person's first name", maxlength=30) + first_name = models.CharField("Person's first name", max_length=30) In this example, the verbose name is ``"first name"``:: - first_name = models.CharField(maxlength=30) + first_name = models.CharField(max_length=30) ``ForeignKey``, ``ManyToManyField`` and ``OneToOneField`` require the first argument to be a model class, so use the ``verbose_name`` keyword argument:: @@ -727,7 +738,7 @@ Many-to-one relationships To define a many-to-one relationship, use ``ForeignKey``. You use it just like any other ``Field`` type: by including it as a class attribute of your model. -``ForeignKey`` requires a positional argument: The class to which the model is +``ForeignKey`` requires a positional argument: the class to which the model is related. For example, if a ``Car`` model has a ``Manufacturer`` -- that is, a @@ -775,7 +786,7 @@ You can, of course, call the field whatever you want. For example:: See the `Many-to-one relationship model example`_ for a full example. -.. _Many-to-one relationship model example: http://www.djangoproject.com/documentation/models/many_to_one/ +.. _Many-to-one relationship model example: ../models/many_to_one/ ``ForeignKey`` fields take a number of extra arguments for defining how the relationship should work. All are optional: @@ -862,7 +873,7 @@ To define a many-to-many relationship, use ``ManyToManyField``. You use it just like any other ``Field`` type: by including it as a class attribute of your model. -``ManyToManyField`` requires a positional argument: The class to which the +``ManyToManyField`` requires a positional argument: the class to which the model is related. For example, if a ``Pizza`` has multiple ``Topping`` objects -- that is, a @@ -902,7 +913,7 @@ set up above, the ``Pizza`` admin form would let users select the toppings. See the `Many-to-many relationship model example`_ for a full example. -.. _Many-to-many relationship model example: http://www.djangoproject.com/documentation/models/many_to_many/ +.. _Many-to-many relationship model example: ../models/many_to_many/ ``ManyToManyField`` objects take a number of extra arguments for defining how the relationship should work. All are optional: @@ -959,7 +970,7 @@ model. This is most useful on the primary key of an object when that object "extends" another object in some way. -``OneToOneField`` requires a positional argument: The class to which the +``OneToOneField`` requires a positional argument: the class to which the model is related. For example, if you're building a database of "places", you would build pretty @@ -979,7 +990,116 @@ as a read-only field when you edit an object in the admin interface: See the `One-to-one relationship model example`_ for a full example. -.. _One-to-one relationship model example: http://www.djangoproject.com/documentation/models/one_to_one/ +.. _One-to-one relationship model example: ../models/one_to_one/ + +Custom field types +------------------ + +**New in Django development version** + +Django's built-in field types don't cover every possible database column type -- +only the common types, such as ``VARCHAR`` and ``INTEGER``. For more obscure +column types, such as geographic polygons or even user-created types such as +`PostgreSQL custom types`_, you can define your own Django ``Field`` subclasses. + +.. _PostgreSQL custom types: http://www.postgresql.org/docs/8.2/interactive/sql-createtype.html + +.. admonition:: Experimental territory + + This is an area of Django that traditionally has not been documented, but + we're starting to include bits of documentation, one feature at a time. + Please forgive the sparseness of this section. + + If you like living on the edge and are comfortable with the risk of + unstable, undocumented APIs, see the code for the core ``Field`` class + in ``django/db/models/fields/__init__.py`` -- but if/when the innards + change, don't say we didn't warn you. + +To create a custom field type, simply subclass ``django.db.models.Field``. +Here is an incomplete list of the methods you should implement: + +``db_type()`` +~~~~~~~~~~~~~ + +Returns the database column data type for the ``Field``, taking into account +the current ``DATABASE_ENGINE`` setting. + +Say you've created a PostgreSQL custom type called ``mytype``. You can use this +field with Django by subclassing ``Field`` and implementing the ``db_type()`` +method, like so:: + + from django.db import models + + class MytypeField(models.Field): + def db_type(self): + return 'mytype' + +Once you have ``MytypeField``, you can use it in any model, just like any other +``Field`` type:: + + class Person(models.Model): + name = models.CharField(max_length=80) + gender = models.CharField(max_length=1) + something_else = MytypeField() + +If you aim to build a database-agnostic application, you should account for +differences in database column types. For example, the date/time column type +in PostgreSQL is called ``timestamp``, while the same column in MySQL is called +``datetime``. The simplest way to handle this in a ``db_type()`` method is to +import the Django settings module and check the ``DATABASE_ENGINE`` setting. +For example:: + + class MyDateField(models.Field): + def db_type(self): + from django.conf import settings + if settings.DATABASE_ENGINE == 'mysql': + return 'datetime' + else: + return 'timestamp' + +The ``db_type()`` method is only called by Django when the framework constructs +the ``CREATE TABLE`` statements for your application -- that is, when you first +create your tables. It's not called at any other time, so it can afford to +execute slightly complex code, such as the ``DATABASE_ENGINE`` check in the +above example. + +Some database column types accept parameters, such as ``CHAR(25)``, where the +parameter ``25`` represents the maximum column length. In cases like these, +it's more flexible if the parameter is specified in the model rather than being +hard-coded in the ``db_type()`` method. For example, it wouldn't make much +sense to have a ``CharMaxlength25Field``, shown here:: + + # This is a silly example of hard-coded parameters. + class CharMaxlength25Field(models.Field): + def db_type(self): + return 'char(25)' + + # In the model: + class MyModel(models.Model): + # ... + my_field = CharMaxlength25Field() + +The better way of doing this would be to make the parameter specifiable at run +time -- i.e., when the class is instantiated. To do that, just implement +``__init__()``, like so:: + + # This is a much more flexible example. + class BetterCharField(models.Field): + def __init__(self, max_length, *args, **kwargs): + self.max_length = max_length + super(BetterCharField, self).__init__(*args, **kwargs) + + def db_type(self): + return 'char(%s)' % self.max_length + + # In the model: + class MyModel(models.Model): + # ... + my_field = BetterCharField(25) + +Note that if you implement ``__init__()`` on a ``Field`` subclass, it's +important to call ``Field.__init__()`` -- i.e., the parent class' +``__init__()`` method. Meta options ============ @@ -987,7 +1107,7 @@ Meta options Give your model metadata by using an inner ``class Meta``, like so:: class Foo(models.Model): - bar = models.CharField(maxlength=30) + bar = models.CharField(max_length=30) class Meta: # ... @@ -1077,7 +1197,7 @@ See `Specifying ordering`_ for more examples. Note that, regardless of how many fields are in ``ordering``, the admin site uses only the first field. -.. _Specifying ordering: http://www.djangoproject.com/documentation/models/ordering/ +.. _Specifying ordering: ../models/ordering/ ``permissions`` --------------- @@ -1161,8 +1281,8 @@ If you want your model to be visible to Django's admin site, give your model an inner ``"class Admin"``, like so:: class Person(models.Model): - first_name = models.CharField(maxlength=30) - last_name = models.CharField(maxlength=30) + first_name = models.CharField(max_length=30) + last_name = models.CharField(max_length=30) class Admin: # Admin options go here @@ -1302,8 +1422,8 @@ that displays the ``__str__()`` representation of each object. A few special cases to note about ``list_display``: - * If the field is a ``ForeignKey``, Django will display the ``__str__()`` - of the related object. + * If the field is a ``ForeignKey``, Django will display the + ``__unicode__()`` of the related object. * ``ManyToManyField`` fields aren't supported, because that would entail executing a separate SQL statement for each row in the table. If you @@ -1321,7 +1441,7 @@ A few special cases to note about ``list_display``: Here's a full example model:: class Person(models.Model): - name = models.CharField(maxlength=50) + name = models.CharField(max_length=50) birthday = models.DateField() class Admin: @@ -1338,9 +1458,9 @@ A few special cases to note about ``list_display``: Here's a full example model:: class Person(models.Model): - first_name = models.CharField(maxlength=50) - last_name = models.CharField(maxlength=50) - color_code = models.CharField(maxlength=6) + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) + color_code = models.CharField(max_length=6) class Admin: list_display = ('first_name', 'last_name', 'colored_name') @@ -1356,7 +1476,7 @@ A few special cases to note about ``list_display``: Here's a full example model:: class Person(models.Model): - first_name = models.CharField(maxlength=50) + first_name = models.CharField(max_length=50) birthday = models.DateField() class Admin: @@ -1367,10 +1487,11 @@ A few special cases to note about ``list_display``: born_in_fifties.boolean = True - * The ``__str__()`` method is just as valid in ``list_display`` as any - other model method, so it's perfectly OK to do this:: + * The ``__str__()`` and ``__unicode__()`` methods are just as valid in + ``list_display`` as any other model method, so it's perfectly OK to do + this:: - list_display = ('__str__', 'some_other_field') + list_display = ('__unicode__', 'some_other_field') * Usually, elements of ``list_display`` that aren't actual database fields can't be used in sorting (because Django does all the sorting at the @@ -1383,8 +1504,8 @@ A few special cases to note about ``list_display``: For example:: class Person(models.Model): - first_name = models.CharField(maxlength=50) - color_code = models.CharField(maxlength=6) + first_name = models.CharField(max_length=50) + color_code = models.CharField(max_length=6) class Admin: list_display = ('first_name', 'colored_first_name') @@ -1552,7 +1673,7 @@ with an operator: AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon') Note that the query input is split by spaces, so, following this example, - it's not currently not possible to search for all records in which + it's currently not possible to search for all records in which ``first_name`` is exactly ``'john winston'`` (containing a space). ``@`` @@ -1634,13 +1755,13 @@ returns a list of all ``OpinionPoll`` objects, each with an extra return result_list class OpinionPoll(models.Model): - question = models.CharField(maxlength=200) + question = models.CharField(max_length=200) poll_date = models.DateField() objects = PollManager() class Response(models.Model): poll = models.ForeignKey(Poll) - person_name = models.CharField(maxlength=50) + person_name = models.CharField(max_length=50) response = models.TextField() With this example, you'd use ``OpinionPoll.objects.with_counts()`` to return @@ -1656,8 +1777,8 @@ A ``Manager``'s base ``QuerySet`` returns all objects in the system. For example, using this model:: class Book(models.Model): - title = models.CharField(maxlength=100) - author = models.CharField(maxlength=50) + title = models.CharField(max_length=100) + author = models.CharField(max_length=50) ...the statement ``Book.objects.all()`` will return all books in the database. @@ -1675,8 +1796,8 @@ all objects, and one that returns only the books by Roald Dahl:: # Then hook it into the Book model explicitly. class Book(models.Model): - title = models.CharField(maxlength=100) - author = models.CharField(maxlength=50) + title = models.CharField(max_length=100) + author = models.CharField(max_length=50) objects = models.Manager() # The default manager. dahl_objects = DahlBookManager() # The Dahl-specific manager. @@ -1709,9 +1830,9 @@ For example:: return super(FemaleManager, self).get_query_set().filter(sex='F') class Person(models.Model): - first_name = models.CharField(maxlength=50) - last_name = models.CharField(maxlength=50) - sex = models.CharField(maxlength=1, choices=(('M', 'Male'), ('F', 'Female'))) + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) + sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female'))) people = models.Manager() men = MaleManager() women = FemaleManager() @@ -1741,11 +1862,11 @@ model. For example, this model has a few custom methods:: class Person(models.Model): - first_name = models.CharField(maxlength=50) - last_name = models.CharField(maxlength=50) + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) birth_date = models.DateField() - address = models.CharField(maxlength=100) - city = models.CharField(maxlength=50) + address = models.CharField(max_length=100) + city = models.CharField(max_length=50) state = models.USStateField() # Yes, this is America-centric... def baby_boomer_status(self): @@ -1776,20 +1897,47 @@ A few object methods have special meaning: ----------- ``__str__()`` is a Python "magic method" that defines what should be returned -if you call ``str()`` on the object. Django uses ``str(obj)`` in a number of -places, most notably as the value displayed to render an object in the Django -admin site and as the value inserted into a template when it displays an -object. Thus, you should always return a nice, human-readable string for the -object's ``__str__``. Although this isn't required, it's strongly encouraged. +if you call ``str()`` on the object. Django uses ``str(obj)`` (or the related +function, ``unicode(obj)`` -- see below) in a number of places, most notably +as the value displayed to render an object in the Django admin site and as the +value inserted into a template when it displays an object. Thus, you should +always return a nice, human-readable string for the object's ``__str__``. +Although this isn't required, it's strongly encouraged (see the description of +``__unicode__``, below, before putting ``_str__`` methods everywhere). For example:: class Person(models.Model): - first_name = models.CharField(maxlength=50) - last_name = models.CharField(maxlength=50) + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) def __str__(self): - return '%s %s' % (self.first_name, self.last_name) + # Note use of django.utils.encoding.smart_str() here because + # first_name and last_name will be unicode strings. + return smart_str('%s %s' % (self.first_name, self.last_name)) + +``__unicode__`` +--------------- + +The ``__unicode__()`` method is called whenever you call ``unicode()`` on an +object. Since Django's database backends will return Unicode strings in your +model's attributes, you would normally want to write a ``__unicode__()`` +method for your model. The example in the previous section could be written +more simply as:: + + class Person(models.Model): + first_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50) + + def __unicode__(self): + return u'%s %s' % (self.first_name, self.last_name) + +If you define a ``__unicode__()`` method on your model and not a ``__str__()`` +method, Django will automatically provide you with a ``__str__()`` that calls +``__unicode()__`` and then converts the result correctly to a UTF-8 encoded +string object. This is recommended development practice: define only +``__unicode__()`` and let Django take care of the conversion to string objects +when required. ``get_absolute_url`` -------------------- @@ -1805,10 +1953,12 @@ Django uses this in its admin interface. If an object defines link that will jump you directly to the object's public view, according to ``get_absolute_url()``. -Also, a couple of other bits of Django, such as the syndication-feed framework, +Also, a couple of other bits of Django, such as the `syndication feed framework`_, use ``get_absolute_url()`` as a convenience to reward people who've defined the method. +.. _syndication feed framework: ../syndication_feeds/ + It's good practice to use ``get_absolute_url()`` in templates, instead of hard-coding your objects' URLs. For example, this template code is bad:: @@ -1823,7 +1973,9 @@ But this template code is good:: characters (required by the URI spec, `RFC 2396`_) that have been URL-encoded, if necessary. Code and templates using ``get_absolute_url()`` should be able to use the result directly without needing to do any - further processing. + further processing. You may wish to use the + ``django.utils.encoding.iri_to_uri()`` function to help with this if you + are using unicode strings a lot. .. _RFC 2396: http://www.ietf.org/rfc/rfc2396.txt @@ -1841,7 +1993,7 @@ works out the correct full URL path using the URLconf, substituting the parameters you have given into the URL. For example, if your URLconf contained a line such as:: - (r'^/people/(\d+)/$', 'people.views.details'), + (r'^people/(\d+)/$', 'people.views.details'), ...your model could have a ``get_absolute_url`` method that looked like this:: @@ -1864,8 +2016,8 @@ Similarly, if you had a URLconf entry that looked like:: 'day': self.created.day}) get_absolute_url = permalink(get_absolute_url) -Notice that we specify an empty sequence for the second argument in this case, -because we only want to pass keyword arguments, not named arguments. +Notice that we specify an empty sequence for the second parameter in this case, +because we only want to pass keyword parameters, not positional ones. In this way, you're tying the model's absolute URL to the view that is used to display it, without repeating the URL information anywhere. You can still @@ -1917,7 +2069,7 @@ A classic use-case for overriding the built-in methods is if you want something to happen whenever you save an object. For example:: class Blog(models.Model): - name = models.CharField(maxlength=100) + name = models.CharField(max_length=100) tagline = models.TextField() def save(self): @@ -1928,7 +2080,7 @@ to happen whenever you save an object. For example:: You can also prevent saving:: class Blog(models.Model): - name = models.CharField(maxlength=100) + name = models.CharField(max_length=100) tagline = models.TextField() def save(self): diff --git a/docs/modpython.txt b/docs/modpython.txt index 388a6168f3..c90296bd9a 100644 --- a/docs/modpython.txt +++ b/docs/modpython.txt @@ -50,8 +50,8 @@ directive. The latter is used for pointing at places on your filesystem, whereas ```` points at places in the URL structure of a Web site. ```` would be meaningless here. -Also, if you've manually altered your ``PYTHONPATH`` to put your Django project -on it, you'll need to tell mod_python: +Also, if your Django project is not on the default ``PYTHONPATH`` for your +computer, you'll have to tell mod_python where your project can be found: .. parsed-literal:: @@ -63,6 +63,30 @@ on it, you'll need to tell mod_python: **PythonPath "['/path/to/project'] + sys.path"** +The value you use for ``PythonPath`` should include the parent directories of +all the modules you are going to import in your application. It should also +include the parent directory of the ``DJANGO_SETTINGS_MODULE`` location. This +is exactly the same situation as setting the Python path for interactive +usage. Whenever you try to import something, Python will run through all the +directories in ``sys.path`` in turn, from first to last, and try to import +from each directory until one succeeds. + +An example might make this clearer. Suppose +you have some applications under ``/usr/local/django-apps/`` (for example, +``/usr/local/django-apps/weblog/`` and so forth), your settings file is at +``/var/www/mysite/settings.py`` and you have specified +``DJANGO_SETTINGS_MODULE`` as in the above example. In this case, you would +need to write your ``PythonPath`` directive as:: + + PythonPath "['/var/production/django-apps/', '/var/www'] + sys.path" + +With this path, ``import weblog`` and ``import mysite.settings`` will both +work. If you had ``import blogroll`` in your code somewhere and ``blogroll`` +lived under the ``weblog/`` directory, you would *also* need to add +``/var/production/django-apps/weblog/`` to your ``PythonPath``. Remember: the +**parent directories** of anything you import directly must be on the Python +path. + .. caution:: If you're using Windows, remember that the path will contain backslashes. diff --git a/docs/newforms.txt b/docs/newforms.txt index 41db04a7dd..0b59a7ad65 100644 --- a/docs/newforms.txt +++ b/docs/newforms.txt @@ -641,7 +641,7 @@ the "Outputting forms as HTML" section above. The simplest way to display a form's HTML is to use the variable on its own, like this:: -
+ {{ form }}
@@ -653,7 +653,7 @@ class' ``__str__()`` method calls its ``as_table()`` method. The following is equivalent but a bit more explicit:: -
+ {{ form.as_table }}
@@ -675,10 +675,10 @@ individual fields for complete template control over the form's design. The easiest way is to iterate over the form's fields, with ``{% for field in form %}``. For example:: -
+
{% for field in form %} -
{{ field.label }}
+
{{ field.label_tag }}
{{ field }}
{% if field.help_text %}
{{ field.help_text }}
{% endif %} {% if field.errors %}
{{ field.errors }}
{% endif %} @@ -696,13 +696,13 @@ Alternatively, you can arrange the form's fields explicitly, by name. Do that by accessing ``{{ form.fieldname }}``, where ``fieldname`` is the field's name. For example:: - +
    -
  • {{ form.sender.label }} {{ form.sender }}
  • +
  • {{ form.sender.label_tag }} {{ form.sender }}
  • {{ form.sender.help_text }}
  • {% if form.sender.errors %}
      {{ form.sender.errors }}
    {% endif %} -
  • {{ form.subject.label }} {{ form.subject }}
  • +
  • {{ form.subject.label_tag }} {{ form.subject }}
  • {{ form.subject.help_text }}
  • {% if form.subject.errors %}
      {{ form.subject.errors }}
    {% endif %} @@ -710,6 +710,49 @@ For example::
+Binding uploaded files to a form +-------------------------------- + +**New in Django development version** + +Dealing with forms that have ``FileField`` and ``ImageField`` fields +is a little more complicated than a normal form. + +Firstly, in order to upload files, you'll need to make sure that your +``
`` element correctly defines the ``enctype`` as +``"multipart/form-data"``:: + + + +Secondly, when you use the form, you need to bind the file data. File +data is handled separately to normal form data, so when your form +contains a ``FileField`` and ``ImageField``, you will need to specify +a second argument when you bind your form. So if we extend our +ContactForm to include an ``ImageField`` called ``mugshot``, we +need to bind the file data containing the mugshot image:: + + # Bound form with an image field + >>> data = {'subject': 'hello', + ... 'message': 'Hi there', + ... 'sender': 'foo@example.com', + ... 'cc_myself': True} + >>> file_data = {'mugshot': {'filename':'face.jpg' + ... 'content': }} + >>> f = ContactFormWithMugshot(data, file_data) + +In practice, you will usually specify ``request.FILES`` as the source +of file data (just like you use ``request.POST`` as the source of +form data):: + + # Bound form with an image field, data from the request + >>> f = ContactFormWithMugshot(request.POST, request.FILES) + +Constructing an unbound form is the same as always -- just omit both +form data *and* file data:: + + # Unbound form with a image field + >>> f = ContactFormWithMugshot() + Subclassing forms ----------------- @@ -919,7 +962,7 @@ validation if a particular field's value is not given. ``initial`` values are ~~~~~~~~~~ The ``widget`` argument lets you specify a ``Widget`` class to use when -rendering this ``Field``. See "Widgets" below for more information. +rendering this ``Field``. See "Widgets"_ below for more information. ``help_text`` ~~~~~~~~~~~~~ @@ -1086,6 +1129,24 @@ If no ``input_formats`` argument is provided, the default input formats are:: '%m/%d/%y %H:%M', # '10/25/06 14:30' '%m/%d/%y', # '10/25/06' +``DecimalField`` +~~~~~~~~~~~~~~~~ + +**New in Django development version** + + * Default widget: ``TextInput`` + * Empty value: ``None`` + * Normalizes to: A Python ``decimal``. + * Validates that the given value is a decimal. Leading and trailing + whitespace is ignored. + +Takes four optional arguments: ``max_value``, ``min_value``, ``max_digits``, +and ``decimal_places``. The first two define the limits for the fields value. +``max_digits`` is the maximum number of digits (those before the decimal +point plus those after the decimal point, with leading zeros stripped) +permitted in the value, whilst ``decimal_places`` is the maximum number of +decimal places permitted. + ``EmailField`` ~~~~~~~~~~~~~~ @@ -1099,6 +1160,54 @@ Has two optional arguments for validation, ``max_length`` and ``min_length``. If provided, these arguments ensure that the string is at most or at least the given length. +``FileField`` +~~~~~~~~~~~~~ + +**New in Django development version** + + * Default widget: ``FileInput`` + * Empty value: ``None`` + * Normalizes to: An ``UploadedFile`` object that wraps the file content + and file name into a single object. + * Validates that non-empty file data has been bound to the form. + +An ``UploadedFile`` object has two attributes: + + ====================== ===================================================== + Argument Description + ====================== ===================================================== + ``filename`` The name of the file, provided by the uploading + client. + ``content`` The array of bytes comprising the file content. + ====================== ===================================================== + +The string representation of an ``UploadedFile`` is the same as the filename +attribute. + +When you use a ``FileField`` on a form, you must also remember to +`bind the file data to the form`_. + +.. _`bind the file data to the form`: `Binding uploaded files to a form`_ + +``ImageField`` +~~~~~~~~~~~~~~ + +**New in Django development version** + + * Default widget: ``FileInput`` + * Empty value: ``None`` + * Normalizes to: An ``UploadedFile`` object that wraps the file content + and file name into a single object. + * Validates that file data has been bound to the form, and that the + file is of an image format understood by PIL. + +Using an ImageField requires that the `Python Imaging Library`_ is installed. + +When you use a ``FileField`` on a form, you must also remember to +`bind the file data to the form`_. + +.. _Python Imaging Library: http://www.pythonware.com/products/pil/ + ``IntegerField`` ~~~~~~~~~~~~~~~~ @@ -1108,6 +1217,9 @@ given length. * Validates that the given value is an integer. Leading and trailing whitespace is allowed, as in Python's ``int()`` function. +Takes two optional arguments for validation, ``max_value`` and ``min_value``. +These control the range of values permitted in the field. + ``MultipleChoiceField`` ~~~~~~~~~~~~~~~~~~~~~~~ @@ -1222,7 +1334,7 @@ Custom form and field validation Form validation happens when the data is cleaned. If you want to customise this process, there are various places you can change, each one serving a -different purpose. Thee types of cleaning methods are run during form +different purpose. Three types of cleaning methods are run during form processing. These are normally executed when you call the ``is_valid()`` method on a form. There are other things that can trigger cleaning and validation (accessing the ``errors`` attribute or calling ``full_clean()`` @@ -1307,12 +1419,12 @@ keep it simple and assume e-mail validation is contained in a function called class MultiEmailField(forms.Field): def clean(self, value): + if not value: + raise forms.ValidationError('Enter at least one e-mail address.') emails = value.split(',') for email in emails: if not is_valid_email(email): raise forms.ValidationError('%s is not a valid e-mail address.' % email) - if not emails: - raise forms.ValidationError('Enter at least one e-mail address.') return emails Let's alter the ongoing ``ContactForm`` example to demonstrate how you'd use @@ -1325,6 +1437,156 @@ like so:: senders = MultiEmailField() cc_myself = forms.BooleanField() +Widgets +======= + +A widget is Django's representation of a HTML input element. The widget +handles the rendering of the HTML, and the extraction of data from a GET/POST +dictionary that corresponds to the widget. + +Django provides a representation of all the basic HTML widgets, plus some +commonly used groups of widgets: + + ============================ =========================================== + Widget HTML Equivalent + ============================ =========================================== + ``TextInput`` ``...`` + ``CheckboxInput`` ``