Fixed a whole bunch of small docs typos, errors, and ommissions.
Fixes #8358, #8396, #8724, #9043, #9128, #9247, #9267, #9267, #9375, #9409, #9414, #9416, #9446, #9454, #9464, #9503, #9518, #9533, #9657, #9658, #9683, #9733, #9771, #9835, #9836, #9837, #9897, #9906, #9912, #9945, #9986, #9992, #10055, #10084, #10091, #10145, #10245, #10257, #10309, #10358, #10359, #10424, #10426, #10508, #10531, #10551, #10635, #10637, #10656, #10658, #10690, #10699, #19528. Thanks to all the respective authors of those tickets. git-svn-id: http://code.djangoproject.com/svn/django/trunk@10371 bcc190cf-cafb-0310-a4f2-bffc1f526a37
| @@ -28,7 +28,9 @@ trailing_empty_content_re = re.compile(r'(?:<p>(?: |\s|<br \/>)*?</p>\s*)+\ | ||||
| del x # Temporary variable | ||||
|  | ||||
| def escape(html): | ||||
|     """Returns the given HTML with ampersands, quotes and carets encoded.""" | ||||
|     """ | ||||
|     Returns the given HTML with ampersands, quotes and angle brackets encoded. | ||||
|     """ | ||||
|     return mark_safe(force_unicode(html).replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"').replace("'", ''')) | ||||
| escape = allow_lazy(escape, unicode) | ||||
|  | ||||
|   | ||||
							
								
								
									
										6
									
								
								docs/_static/djangodocs.css
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -103,9 +103,9 @@ dt .literal, table .literal { background:none; } | ||||
| .note, .admonition { padding:.8em 1em .8em; margin: 1em 0; border:1px solid #94da3a; } | ||||
| .admonition-title { font-weight:bold; margin-top:0 !important; margin-bottom:0 !important;} | ||||
| .admonition .last { margin-bottom:0 !important; } | ||||
| .note, .admonition { padding-left:65px; background:url(docicons-note.gif) .8em .8em no-repeat;} | ||||
| div.admonition-philosophy { padding-left:65px; background:url(docicons-philosophy.gif) .8em .8em no-repeat;} | ||||
| div.admonition-behind-the-scenes { padding-left:65px; background:url(docicons-behindscenes.gif) .8em .8em no-repeat;} | ||||
| .note, .admonition { padding-left:65px; background:url(docicons-note.png) .8em .8em no-repeat;} | ||||
| div.admonition-philosophy { padding-left:65px; background:url(docicons-philosophy.png) .8em .8em no-repeat;} | ||||
| div.admonition-behind-the-scenes { padding-left:65px; background:url(docicons-behindscenes.png) .8em .8em no-repeat;} | ||||
|  | ||||
| /*** versoinadded/changes ***/ | ||||
| div.versionadded, div.versionchanged {  } | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								docs/_static/docicons-behindscenes.gif
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 1.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/_static/docicons-behindscenes.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/_static/docicons-note.gif
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 632 B | 
							
								
								
									
										
											BIN
										
									
								
								docs/_static/docicons-note.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1013 B | 
							
								
								
									
										
											BIN
										
									
								
								docs/_static/docicons-philosophy.gif
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 799 B | 
							
								
								
									
										
											BIN
										
									
								
								docs/_static/docicons-philosophy.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.5 KiB | 
| @@ -63,7 +63,11 @@ backend storage system. | ||||
|  | ||||
| Called by ``Storage.save()``. The ``name`` will already have gone through | ||||
| ``get_valid_name()`` and ``get_available_name()``, and the ``content`` will be a | ||||
| ``File`` object itself. No return value is expected. | ||||
| ``File`` object itself.  | ||||
|  | ||||
| Should return the actual name of name of the file saved (usually the ``name`` | ||||
| passed in, but if the storage needs to change the file name return the new name | ||||
| instead). | ||||
|  | ||||
| ``get_valid_name(name)`` | ||||
| ------------------------ | ||||
|   | ||||
| @@ -17,14 +17,22 @@ performance gains over other server arrangements. | ||||
| Django requires Apache 2.x and mod_python 3.x, and you should use Apache's | ||||
| `prefork MPM`_, as opposed to the `worker MPM`_. | ||||
|  | ||||
| You may also be interested in :ref:`How to use Django with FastCGI, SCGI, or | ||||
| AJP <howto-deployment-fastcgi>`. | ||||
| .. seealso:: | ||||
|  | ||||
|     * Apache is a big, complex animal, and this document only scratches the | ||||
|       surface of what Apache can do. If you need more advanced information about | ||||
|       Apache, there's no better source than `Apache's own official | ||||
|       documentation`_ | ||||
|  | ||||
|     * You may also be interested in :ref:`How to use Django with FastCGI, SCGI, | ||||
|       or AJP <howto-deployment-fastcgi>`. | ||||
|  | ||||
| .. _Apache: http://httpd.apache.org/ | ||||
| .. _mod_python: http://www.modpython.org/ | ||||
| .. _mod_perl: http://perl.apache.org/ | ||||
| .. _prefork MPM: http://httpd.apache.org/docs/2.2/mod/prefork.html | ||||
| .. _worker MPM: http://httpd.apache.org/docs/2.2/mod/worker.html | ||||
| .. _apache's own official documentation: http://httpd.apache.org/docs/ | ||||
|  | ||||
| Basic configuration | ||||
| =================== | ||||
| @@ -52,15 +60,15 @@ Django mod_python handler." It passes the value of :ref:`DJANGO_SETTINGS_MODULE | ||||
| .. versionadded:: 1.0 | ||||
|     The ``PythonOption django.root ...`` is new in this version. | ||||
|  | ||||
| Because mod_python does not know we are | ||||
| serving this site from underneath the ``/mysite/`` prefix, this value needs to | ||||
| be passed through to the mod_python handler in Django, via the ``PythonOption | ||||
| django.root ...`` line. The value set on that line (the last item) should | ||||
| match the string given in the ``<Location ...>`` directive. The effect of this | ||||
| is that Django will automatically strip the ``/mysite`` string from the front | ||||
| of any URLs before matching them against your URLconf patterns. If you later | ||||
| move your site to live under ``/mysite2``, you will not have to change anything | ||||
| except the ``django.root`` option in the config file. | ||||
| Because mod_python does not know we are serving this site from underneath the | ||||
| ``/mysite/`` prefix, this value needs to be passed through to the mod_python | ||||
| handler in Django, via the ``PythonOption django.root ...`` line. The value set | ||||
| on that line (the last item) should match the string given in the ``<Location | ||||
| ...>`` directive. The effect of this is that Django will automatically strip the | ||||
| ``/mysite`` string from the front of any URLs before matching them against your | ||||
| URLconf patterns. If you later move your site to live under ``/mysite2``, you | ||||
| will not have to change anything except the ``django.root`` option in the config | ||||
| file. | ||||
|  | ||||
| When using ``django.root`` you should make sure that what's left, after the | ||||
| prefix has been removed, begins with a slash. Your URLconf patterns that are | ||||
| @@ -97,6 +105,10 @@ 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. | ||||
|  | ||||
| Make sure that your Python source files' permissions are set such that the | ||||
| Apache user (usually named ``apache`` or ``httpd`` on most systems) will have | ||||
| read access to the files. | ||||
|  | ||||
| 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 | ||||
|   | ||||
| @@ -47,7 +47,7 @@ look like in JSON: | ||||
|           "first_name": "Paul", | ||||
|           "last_name": "McCartney" | ||||
|         } | ||||
|       }, | ||||
|       } | ||||
|     ] | ||||
|  | ||||
| And here's that same fixture as YAML: | ||||
|   | ||||
| @@ -10,9 +10,9 @@ How to serve static files | ||||
| Django itself doesn't serve static (media) files, such as images, style sheets, | ||||
| or video. It leaves that job to whichever Web server you choose. | ||||
|  | ||||
| The reasoning here is that standard Web servers, such as Apache_, lighttpd_ and Cherokee_, | ||||
| are much more fine-tuned at serving static files than a Web application | ||||
| framework. | ||||
| The reasoning here is that standard Web servers, such as Apache_, lighttpd_ and | ||||
| Cherokee_, are much more fine-tuned at serving static files than a Web | ||||
| application framework. | ||||
|  | ||||
| With that said, Django does support static files **during development**. You can | ||||
| use the :func:`django.views.static.serve` view to serve media files. | ||||
| @@ -21,6 +21,11 @@ use the :func:`django.views.static.serve` view to serve media files. | ||||
| .. _lighttpd: http://www.lighttpd.net/ | ||||
| .. _Cherokee: http://www.cherokee-project.com/ | ||||
|  | ||||
| .. seealso:: | ||||
|  | ||||
|     If you just need to serve the admin media from a nonstandard location, see | ||||
|     the :djadminopt:`--adminmedia` parameter to :djadmin:`runserver`. | ||||
|  | ||||
| The big, fat disclaimer | ||||
| ======================= | ||||
|  | ||||
|   | ||||
| @@ -134,18 +134,27 @@ It worked! | ||||
| .. admonition:: Changing the port | ||||
|  | ||||
|     By default, the :djadmin:`runserver` command starts the development server | ||||
|     on port 8000. If you want to change the server's port, pass it as a | ||||
|     command-line argument. For instance, this command starts the server on port | ||||
|     8080: | ||||
|     on the internal IP at port 8000.  | ||||
|      | ||||
|     If you want to change the server's port, pass | ||||
|     it as a command-line argument. For instance, this command starts the server | ||||
|     on port 8080: | ||||
|      | ||||
|     .. code-block:: bash | ||||
|  | ||||
|         python manage.py runserver 8080 | ||||
|          | ||||
|     If you want to change the server's IP, pass it along with the port. So to | ||||
|     listen on all public IPs (useful if you want to show off your work on other | ||||
|     computers), use: | ||||
|      | ||||
|     .. code-block:: bash | ||||
|      | ||||
|         python manage.py runserver 0.0.0.0:8000 | ||||
|  | ||||
|     Full docs for the development server can be found in the | ||||
|     :djadmin:`runserver` reference. | ||||
|  | ||||
|  | ||||
| Database setup | ||||
| -------------- | ||||
|  | ||||
|   | ||||
| @@ -302,6 +302,13 @@ for a given poll. Here's the view:: | ||||
| The new concept here: The view raises the :exc:`~django.http.Http404` exception | ||||
| if a poll with the requested ID doesn't exist. | ||||
|  | ||||
| We'll discuss what you could put in that ``polls/detail.html`` template a bit | ||||
| later, but if you'd like to quickly get the above example working, just:: | ||||
|  | ||||
|     {{ poll }} | ||||
|      | ||||
| will get you started for now. | ||||
|  | ||||
| A shortcut: get_object_or_404() | ||||
| ------------------------------- | ||||
|  | ||||
| @@ -357,6 +364,10 @@ in ``django/conf/urls/defaults.py``, ``handler404`` is set to | ||||
|  | ||||
| Three more things to note about 404 views: | ||||
|  | ||||
|     * If :setting:`DEBUG` is set to ``True`` (in your settings module) then your | ||||
|       404 view will never be used (and thus the ``404.html`` template will never | ||||
|       be rendered) because the traceback will be displayed instead. | ||||
|  | ||||
|     * The 404 view is also called if Django doesn't find a match after checking | ||||
|       every regular expression in the URLconf. | ||||
|        | ||||
| @@ -365,8 +376,9 @@ Three more things to note about 404 views: | ||||
|       template in the root of your template directory. The default 404 view will | ||||
|       use that template for all 404 errors. | ||||
|        | ||||
|     * If :setting:`DEBUG` is set to ``True`` (in your settings module) then your | ||||
|       404 view will never be used, and the traceback will be displayed instead. | ||||
|     * If :setting:`DEBUG` is set to ``False`` (in your settings module) and if | ||||
|       you didn't create a ``404.html`` file, an ``Http500`` is raised instead. | ||||
|       So remember to create a ``404.html``. | ||||
|  | ||||
| Write a 500 (server error) view | ||||
| =============================== | ||||
|   | ||||
| @@ -20,7 +20,7 @@ tutorial, so that the template contains an HTML ``<form>`` element: | ||||
|  | ||||
|     {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} | ||||
|  | ||||
|     <form action="/polls/{{ poll.id }}/vote/" method="post"> | ||||
|     <form action="vote/" method="post"> | ||||
|     {% for choice in poll.choice_set.all %} | ||||
|         <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /> | ||||
|         <label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br /> | ||||
| @@ -36,12 +36,12 @@ A quick rundown: | ||||
|       selects one of the radio buttons and submits the form, it'll send the | ||||
|       POST data ``choice=3``. This is HTML Forms 101. | ||||
|  | ||||
|     * We set the form's ``action`` to ``/polls/{{ poll.id }}/vote/``, and we | ||||
|       set ``method="post"``. Using ``method="post"`` (as opposed to | ||||
|       ``method="get"``) is very important, because the act of submitting this | ||||
|       form will alter data server-side. Whenever you create a form that alters | ||||
|       data server-side, use ``method="post"``. This tip isn't specific to | ||||
|       Django; it's just good Web development practice. | ||||
|     * We set the form's ``action`` to ``vote/``, and we set ``method="post"``. | ||||
|       Using ``method="post"`` (as opposed to ``method="get"``) is very | ||||
|       important, because the act of submitting this form will alter data | ||||
|       server-side. Whenever you create a form that alters data server-side, use | ||||
|       ``method="post"``. This tip isn't specific to Django; it's just good Web | ||||
|       development practice. | ||||
|  | ||||
|     * ``forloop.counter`` indicates how many times the :ttag:`for` tag has gone | ||||
|       through its loop | ||||
| @@ -170,7 +170,17 @@ to write Python code to write an app. | ||||
|  | ||||
| Let's convert our poll app to use the generic views system, so we can delete a | ||||
| bunch of our own code. We'll just have to take a few steps to make the | ||||
| conversion. | ||||
| conversion. We will: | ||||
|  | ||||
|     1. Convert the URLconf. | ||||
|      | ||||
|     2. Rename a few templates. | ||||
|      | ||||
|     3. Delete some the old, now unneeded views. | ||||
|      | ||||
|     4. Fix up URL handling for the new views. | ||||
|  | ||||
| Read on for details. | ||||
|  | ||||
| .. admonition:: Why the code-shuffle? | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
| Third-party distributions of Django | ||||
| =================================== | ||||
|  | ||||
| Several third-party distributors are now providing versions of Django integrated | ||||
| Many third-party distributors are now providing versions of Django integrated | ||||
| with their package-management systems. These can make installation and upgrading | ||||
| much easier for users of Django since the integration includes the ability to | ||||
| automatically install dependencies (like database adapters) that Django | ||||
| @@ -15,81 +15,14 @@ if you want to use the development version of Django you'll need to follow the | ||||
| instructions for :ref:`installing the development version | ||||
| <installing-development-version>` from our Subversion repository. | ||||
|  | ||||
| FreeBSD | ||||
| ======= | ||||
| If you're using Linux or a Unix installation, such as OpenSolaris, | ||||
| check with your distributor to see if they already package Django. If | ||||
| you're using a Linux distro and don't know how to find out if a package | ||||
| is available, then now is a good time to learn.  The Django Wiki contains | ||||
| a list of `Third Party Distributions`_ to help you out. | ||||
|  | ||||
| The `FreeBSD`_ ports system offers both Django 0.96 (`py-django`_) and a more | ||||
| recent, but not current, version based on Django's trunk (`py-django-devel`_). | ||||
| These are installed in the normal FreeBSD way; for Django 0.96, for example, type: | ||||
| ``cd /usr/ports/www/py-django && sudo make install clean``. | ||||
| .. _`Third Party Distributions`: http://code.djangoproject.com/wiki/Distributions | ||||
|  | ||||
| .. _FreeBSD: http://www.freebsd.org/ | ||||
| .. _py-django: http://www.freebsd.org/cgi/cvsweb.cgi/ports/www/py-django/ | ||||
| .. _py-django-devel: http://www.freebsd.org/cgi/cvsweb.cgi/ports/www/py-django-devel/ | ||||
|  | ||||
| Linux distributions | ||||
| =================== | ||||
|  | ||||
| Debian | ||||
| ------ | ||||
|  | ||||
| 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/stable/python/python-django | ||||
|  | ||||
| Fedora | ||||
| ------ | ||||
|  | ||||
| A Django package is available for `Fedora Linux`_, in the "Fedora Extras" | ||||
| repository. The `current Fedora package`_ is based on Django 0.96, and can be | ||||
| installed by typing ``yum install Django``. The previous link is for the i386 | ||||
| binary. Users of other architectures should be able to use that as a starting | ||||
| point to find their preferred version. | ||||
|  | ||||
| .. _Fedora Linux: http://fedora.redhat.com/ | ||||
| .. _current Fedora package: http://download.fedora.redhat.com/pub/fedora/linux/extras/6/i386/repoview/Django.html | ||||
|  | ||||
| Gentoo | ||||
| ------ | ||||
|  | ||||
| A Django package is available for `Gentoo Linux`_, and is based on Django 0.96.1. | ||||
| The `current Gentoo package`_ can be installed by typing ``emerge django``. | ||||
|  | ||||
| .. _Gentoo Linux: http://www.gentoo.org/ | ||||
| .. _current Gentoo package: http://packages.gentoo.org/package/django | ||||
|  | ||||
| Ubuntu | ||||
| ------ | ||||
|  | ||||
| The Debian ``python-django`` package is also available for `Ubuntu Linux`_, in | ||||
| the "universe" repository for Ubuntu 7.10 ("Gutsy Gibbon"). The `current Ubuntu | ||||
| package`_ is based on Django 0.96.1 and can be installed in the same fashion as | ||||
| for Debian. | ||||
|  | ||||
| .. _Ubuntu Linux: http://www.ubuntu.com/ | ||||
| .. _current Ubuntu package: http://packages.ubuntu.com/gutsy/python/python-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 | ||||
| ================ | ||||
|   | ||||
| Before Width: | Height: | Size: 8.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/obsolete/_images/formrow.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 16 KiB | 
| Before Width: | Height: | Size: 5.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/obsolete/_images/module.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 9.8 KiB | 
| Before Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/obsolete/_images/objecttools_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.4 KiB | 
| Before Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/obsolete/_images/objecttools_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.2 KiB | 
| @@ -29,7 +29,7 @@ group in a box and applies certain styles to the elements within. An ``h2`` | ||||
| within a ``div.module`` will align to the top of the ``div`` as a header for the | ||||
| whole group. | ||||
|  | ||||
| .. image:: _images/module.gif | ||||
| .. image:: _images/module.png | ||||
|    :alt: Example use of module class on admin homepage | ||||
|  | ||||
| Column Types | ||||
| @@ -134,7 +134,7 @@ Example from a changelist page: | ||||
|       <li><a href="/stories/add/" class="addlink">Add redirect</a></li> | ||||
|     </ul> | ||||
|  | ||||
| .. image:: _images/objecttools_01.gif | ||||
| .. image:: _images/objecttools_01.png | ||||
|    :alt: Object tools on a changelist page | ||||
|  | ||||
| and from a form page: | ||||
| @@ -146,7 +146,7 @@ and from a form page: | ||||
|      <li><a href="/r/303/152383/" class="viewsitelink">View on site</a></li> | ||||
|     </ul> | ||||
|  | ||||
| .. image:: _images/objecttools_02.gif | ||||
| .. image:: _images/objecttools_02.png | ||||
|    :alt: Object tools on a form page | ||||
|  | ||||
| Form Styles | ||||
| @@ -176,7 +176,7 @@ Each row of the form (within the ``fieldset``) should be enclosed in a ``div`` | ||||
| with class ``form-row``. If the field in the row is required, a class of | ||||
| ``required`` should also be added to the ``div.form-row``. | ||||
|  | ||||
| .. image:: _images/formrow.gif | ||||
| .. image:: _images/formrow.png | ||||
|    :alt: Example use of form-row class | ||||
|  | ||||
| Labels | ||||
|   | ||||
| @@ -46,6 +46,11 @@ Other topics | ||||
|    :maxdepth: 1 | ||||
|  | ||||
|    actions | ||||
|     | ||||
| .. seealso:: | ||||
|  | ||||
|     For information about serving the media files (images, JavaScript, and CSS) | ||||
|     associated with the admin in production, see :ref:`serving-media-files`. | ||||
|  | ||||
| ``ModelAdmin`` objects | ||||
| ====================== | ||||
| @@ -425,8 +430,8 @@ edit and save multiple rows at once. | ||||
|     ``list_editable`` interacts with a couple of other options in particular | ||||
|     ways; you should note the following rules: | ||||
|  | ||||
|         * To use ``list_editable`` you must have defined ``ordering`` on | ||||
|           either your model or your ``ModelAdmin``. | ||||
|         * To use ``list_editable`` you must have defined ``ordering`` on either | ||||
|           your model's or your ``ModelAdmin``'s inner ``Meta``. | ||||
|  | ||||
|         * Any field in ``list_editable`` must also be in ``list_display``. You | ||||
|           can't edit a field that's not displayed! | ||||
| @@ -1155,6 +1160,37 @@ If you wish to change the index or login templates, you are better off creating | ||||
| your own ``AdminSite`` instance (see below), and changing the ``index_template`` | ||||
| or ``login_template`` properties. | ||||
|  | ||||
| Linking to admin views | ||||
| ====================== | ||||
|  | ||||
| .. versionadded:: 1.1 | ||||
|  | ||||
| All the admin views use :ref:`named URL patterns <naming-url-patterns>` so it's | ||||
| easy to link to admin views with ``urlresolvers.reverse`` or the :ttag:`url` | ||||
| template tag.  | ||||
|  | ||||
| Each model gets its own set of views and its own name using the model's app name | ||||
| and model name. For example, the "add" view for a ``Choice`` model in a | ||||
| ``polls`` app would be named ``"admin_polls_choice_add"``. | ||||
|  | ||||
| All the available views and their names are: | ||||
|  | ||||
|     ==============  ======================================  =================== | ||||
|     View            View name                               Parameters | ||||
|     ==============  ======================================  =================== | ||||
|     Change list     ``"admin_<app>_<model>_changelist"``    None | ||||
|     Add object      ``"admin_<app>_<model>_add"``           None | ||||
|     Change object   ``"admin_<app>_<model>_change"``        ``object_id`` | ||||
|     Delete object   ``"admin_<app>_<model>_delete"``        ``object_id`` | ||||
|     Object history  ``"admin_<app>_<model>_history"``       ``object_id`` | ||||
|     ==============  ======================================  =================== | ||||
|  | ||||
| For example, to get the change URL for a particular ``Choice`` object:: | ||||
|  | ||||
|     >>> from django.core import urlresolvers | ||||
|     >>> c = Choice.objects.get(...) | ||||
|     >>> change_url = urlresolvers.reverse('admin_polls_choice_change', (c.id,)) | ||||
|  | ||||
| ``AdminSite`` objects | ||||
| ===================== | ||||
|  | ||||
|   | ||||
| @@ -99,6 +99,10 @@ For example:: | ||||
|     {% for comment in comment_list %} | ||||
|         ... | ||||
|     {% endfor %} | ||||
|      | ||||
| This returns a list of :class:`~django.contrib.comments.models.Comment` objects; | ||||
| see :ref:`the comment model documentation <ref-contrib-comments-models>` for | ||||
| details. | ||||
|  | ||||
| .. templatetag:: get_comment_count | ||||
|  | ||||
| @@ -212,6 +216,7 @@ More information | ||||
| .. toctree:: | ||||
|    :maxdepth: 1 | ||||
|  | ||||
|    models | ||||
|    settings | ||||
|    signals | ||||
|    upgrade | ||||
|   | ||||
							
								
								
									
										82
									
								
								docs/ref/contrib/comments/models.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,82 @@ | ||||
| .. _ref-contrib-comments-models: | ||||
|  | ||||
| =========================== | ||||
| The built-in comment models | ||||
| =========================== | ||||
|  | ||||
| .. module:: django.contrib.comments.models | ||||
|    :synopsis: The built-in comment models | ||||
|    | ||||
| .. class:: Comment | ||||
|  | ||||
|     Django's built-in comment model. Has the following fields: | ||||
|      | ||||
|     .. attribute:: content_object | ||||
|      | ||||
|         A :class:`~django.contrib.contettypes.generic.GenericForeignKey` | ||||
|         attribute pointing to the object the comment is attached to. You can use | ||||
|         this to get at the related object (i.e. ``my_comment.content_object``). | ||||
|          | ||||
|         Since this field is a | ||||
|         :class:`~django.contrib.contettypes.generic.GenericForeignKey`, it's | ||||
|         actually syntactic sugar on top of two underlying attributes, described | ||||
|         below. | ||||
|      | ||||
|     .. attribute:: content_type | ||||
|     | ||||
|         A :class:`~django.db.models.ForeignKey` to | ||||
|         :class:`~django.contrib.contenttypes.models.ContentType`; this is the | ||||
|         type of the object the comment is attached to. | ||||
|        | ||||
|     .. attribute:: object_pk | ||||
|      | ||||
|         A :class:`~django.db.models.TextField` containing the primary | ||||
|         key of the object the comment is attached to. | ||||
|          | ||||
|     .. attribute:: site | ||||
|      | ||||
|         A :class:`~django.db.models.ForeignKey` to the | ||||
|         :class:`~django.contrib.sites.models.Site` on which the comment was | ||||
|         posted. | ||||
|          | ||||
|     .. attribute:: user | ||||
|      | ||||
|         A :class:`~django.db.models.ForeignKey` to the | ||||
|         :class:`~django.contrib.auth.models.User` who posted the comment. | ||||
|         May be blank if the comment was posted by an unauthenticated user. | ||||
|          | ||||
|     .. attribute:: user_name | ||||
|      | ||||
|         The name of the user who posted the comment. | ||||
|      | ||||
|     .. attribute:: user_email | ||||
|      | ||||
|         The email of the user who posteed the comment. | ||||
|      | ||||
|     .. attribute:: user_url | ||||
|      | ||||
|         The URL entered by the person who posted the comment. | ||||
|      | ||||
|     .. attribute:: comment | ||||
|      | ||||
|         The actual content of the comment itself. | ||||
|      | ||||
|     .. attribute:: submit_date | ||||
|      | ||||
|         The date the comment was submitted. | ||||
|      | ||||
|     .. attribute:: ip_address | ||||
|      | ||||
|         The IP address of the user posting the comment. | ||||
|      | ||||
|     .. attribute:: is_public | ||||
|      | ||||
|         ``False`` if the comment is in moderation (see | ||||
|         :ref:`ref-contrib-comments-moderation`); If ``True``, the comment will | ||||
|         be displayed on the site. | ||||
|      | ||||
|     .. attribute:: is_removed | ||||
|      | ||||
|         ``True`` if the comment was removed. Used to keep track of removed | ||||
|         comments instead of just deleting them. | ||||
|          | ||||
| @@ -39,6 +39,11 @@ To install the flatpages app, follow these steps: | ||||
|        ``'django.contrib.sites'`` to your :setting:`INSTALLED_APPS` setting, | ||||
|        if it's not already in there. | ||||
|         | ||||
|        Also make sure you've correctly set :setting:`SITE_ID` to the ID of the | ||||
|        site the settings file represents. This will usually be ``1`` (i.e. | ||||
|        ``SITE_ID = 1``, but if you're not using the sites framework to manage | ||||
|        multiple sites, it could be the ID of a different site. | ||||
|         | ||||
|     2. Add ``'django.contrib.flatpages'`` to your :setting:`INSTALLED_APPS` | ||||
|        setting. | ||||
|         | ||||
|   | ||||
| @@ -160,11 +160,11 @@ into those elements. | ||||
|       :class:`~django.contrib.syndication.feeds.Feed` class. | ||||
|  | ||||
|     * To specify the contents of ``<link>``, you have two options. For each item | ||||
|       in :meth:`items()`, Django first tries executing a ``get_absolute_url()`` | ||||
|       method on that object. If that method doesn't exist, it tries calling a | ||||
|       method :meth:`item_link()` in the | ||||
|       :class:`~django.contrib.syndication.feeds.Feed` class, passing it a single | ||||
|       parameter, :attr:`item`, which is the object itself. Both | ||||
|       in :meth:`items()`, Django first tries calling a method | ||||
|       :meth:`item_link()` in the :class:`~django.contrib.syndication.feeds.Feed` | ||||
|       class, passing it a single parameter, :attr:`item`, which is the object | ||||
|       itself. If that method doesn't exist, Django tries executing a | ||||
|       ``get_absolute_url()`` method on that object. . Both | ||||
|       ``get_absolute_url()`` and :meth:`item_link()` should return the item's | ||||
|       URL as a normal Python string. As with ``get_absolute_url()``, the result | ||||
|       of :meth:`item_link()` will be included directly in the URL, so you are | ||||
| @@ -644,9 +644,8 @@ This example illustrates all possible attributes and methods for a | ||||
|             Returns the URL for every item in the feed. | ||||
|             """ | ||||
|  | ||||
|         # ITEM_GUID -- The following method is optional. This property is | ||||
|         # only used for Atom feeds (it is the ID element for an item in an | ||||
|         # Atom feed). If not provided, the item's link is used by default. | ||||
|         # ITEM_GUID -- The following method is optional. If not provided, the | ||||
|         # item's link is used by default. | ||||
|  | ||||
|         def item_guid(self, obj): | ||||
|             """ | ||||
|   | ||||
| @@ -80,7 +80,6 @@ You should also audit your existing code for any instances of this behavior | ||||
| before enabling this feature. It's faster, but it provides less automatic | ||||
| protection for multi-call operations. | ||||
|  | ||||
|  | ||||
| .. _mysql-notes: | ||||
|  | ||||
| MySQL notes | ||||
| @@ -247,18 +246,18 @@ anything in a `MySQL option file`_. | ||||
|  | ||||
| Here's a sample configuration which uses a MySQL option file:: | ||||
|  | ||||
|   # settings.py | ||||
|   DATABASE_ENGINE = "mysql" | ||||
|   DATABASE_OPTIONS = { | ||||
|       'read_default_file': '/path/to/my.cnf', | ||||
|   } | ||||
|  | ||||
|   # my.cnf | ||||
|   [client] | ||||
|   database = DATABASE_NAME | ||||
|   user = DATABASE_USER | ||||
|   password = DATABASE_PASSWORD | ||||
|   default-character-set = utf8 | ||||
|     # settings.py | ||||
|     DATABASE_ENGINE = "mysql" | ||||
|     DATABASE_OPTIONS = { | ||||
|         'read_default_file': '/path/to/my.cnf', | ||||
|     } | ||||
|      | ||||
|     # my.cnf | ||||
|     [client] | ||||
|     database = DATABASE_NAME | ||||
|     user = DATABASE_USER | ||||
|     password = DATABASE_PASSWORD | ||||
|     default-character-set = utf8 | ||||
|  | ||||
| Several other MySQLdb connection options may be useful, such as ``ssl``, | ||||
| ``use_unicode``, ``init_command``, and ``sql_mode``. Consult the | ||||
| @@ -426,6 +425,42 @@ This provides the ability to upgrade both the DB-API 2.0 interface or SQLite 3 | ||||
| itself to versions newer than the ones included with your particular Python | ||||
| binary distribution, if needed. | ||||
|  | ||||
| "Database is locked" errors | ||||
| ----------------------------------------------- | ||||
|  | ||||
| SQLite is meant to be a lightweight database, and thus can't support a high | ||||
| level of concurrency. ``OperationalError: database is locked`` errors indicate | ||||
| that your application is experiencing more concurrency than ``sqlite`` can | ||||
| handle in default configuration. This error means that one thread or process has | ||||
| an exclusive lock on the database connection and another thread timed out | ||||
| waiting for the lock the be released. | ||||
|  | ||||
| Python's SQLite wrapper has | ||||
| a default timeout value that determines how long the second thread is allowed to | ||||
| wait on the lock before it times out and raises the ``OperationalError: database | ||||
| is locked`` error. | ||||
|  | ||||
| If you're getting this error, you can solve it by: | ||||
|  | ||||
|     * Switching to another database backend. At a certain point SQLite becomes | ||||
|       too "lite" for real-world applications, and these sorts of concurrency | ||||
|       errors indicate you've reached that point. | ||||
|        | ||||
|     * Rewriting your code to reduce concurrency and ensure that database  | ||||
|       transactions are short-lived. | ||||
|        | ||||
|     * Increase the default timeout value by setting the ``timeout`` database | ||||
|       option option:: | ||||
|  | ||||
|           DATABASE_OPTIONS = { | ||||
|               # ... | ||||
|              "timeout": 20, | ||||
|               # ... | ||||
|           } | ||||
|        | ||||
|       This will simply make SQLite wait a bit longer before throwing "database | ||||
|       is locked" errors; it won't really do anything to solve them. | ||||
|  | ||||
| .. _oracle-notes: | ||||
|  | ||||
| Oracle notes | ||||
|   | ||||
| @@ -458,8 +458,10 @@ supports the FastCGI protocol. See the :ref:`FastCGI deployment documentation | ||||
|  | ||||
| .. _flup: http://www.saddi.com/software/flup/ | ||||
|  | ||||
| runserver [optional port number, or ipaddr:port] | ||||
| ------------------------------------------------ | ||||
| runserver | ||||
| --------- | ||||
|  | ||||
| .. django-admin:: runserver [port or ipaddr:port] | ||||
|  | ||||
| Starts a lightweight development Web server on the local machine. By default, | ||||
| the server runs on port 8000 on the IP address 127.0.0.1. You can pass in an | ||||
| @@ -491,8 +493,7 @@ machines on your network. To make your development server viewable to other | ||||
| machines on the network, use its own IP address (e.g. ``192.168.2.1``) or | ||||
| ``0.0.0.0``. | ||||
|  | ||||
| --adminmedia | ||||
| ~~~~~~~~~~~~ | ||||
| .. django-admin-option:: --adminmedia | ||||
|  | ||||
| Use the ``--adminmedia`` option to tell Django where to find the various CSS | ||||
| and JavaScript files for the Django admin interface. Normally, the development | ||||
| @@ -503,8 +504,7 @@ Example usage:: | ||||
|  | ||||
|     django-admin.py runserver --adminmedia=/tmp/new-admin-style/ | ||||
|  | ||||
| --noreload | ||||
| ~~~~~~~~~~ | ||||
| .. django-admin-option:: --noreload | ||||
|  | ||||
| Use the ``--noreload`` option to disable the use of the auto-reloader. This | ||||
| means any Python code changes you make while the server is running will *not* | ||||
| @@ -541,14 +541,6 @@ By default, the development server doesn't serve any static files for your site | ||||
| (such as CSS files, images, things under ``MEDIA_URL`` and so forth). If | ||||
| you want to configure Django to serve static media, read :ref:`howto-static-files`. | ||||
|  | ||||
| Turning off auto-reload | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| To disable auto-reloading of code while the development server is running, use the | ||||
| ``--noreload`` option, like so:: | ||||
|  | ||||
|     django-admin.py runserver --noreload | ||||
|  | ||||
| shell | ||||
| ----- | ||||
|  | ||||
|   | ||||
| @@ -129,6 +129,40 @@ what happens with unbound forms:: | ||||
|     >>> f.errors | ||||
|     {} | ||||
|  | ||||
| Dynamic initial values | ||||
| ---------------------- | ||||
|  | ||||
| .. attribute:: Form.initial | ||||
|  | ||||
| Use ``initial`` to declare the initial value of form fields at runtime. For | ||||
| example, you might want to fill in a ``username`` field with the username of the | ||||
| current session. | ||||
|  | ||||
| To accomplish this, use the ``initial`` argument to a ``Form``. This argument, | ||||
| if given, should be a dictionary mapping field names to initial values. Only | ||||
| include the fields for which you're specifying an initial value; it's not | ||||
| necessary to include every field in your form. For example:: | ||||
|  | ||||
|     >>> f = ContactForm(initial={'subject': 'Hi there!'}) | ||||
|  | ||||
| These values are only displayed for unbound forms, and they're not used as | ||||
| fallback values if a particular value isn't provided. | ||||
|  | ||||
| Note that if a ``Field`` defines ``initial`` *and* you include ``initial`` when | ||||
| instantiating the ``Form``, then the latter ``initial`` will have precedence. In | ||||
| this example, ``initial`` is provided both at the field level and at the form | ||||
| instance level, and the latter gets precedence:: | ||||
|  | ||||
|     >>> class CommentForm(forms.Form): | ||||
|     ...     name = forms.CharField(initial='class') | ||||
|     ...     url = forms.URLField() | ||||
|     ...     comment = forms.CharField() | ||||
|     >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False) | ||||
|     >>> print f | ||||
|     <tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr> | ||||
|     <tr><th>Url:</th><td><input type="text" name="url" /></td></tr> | ||||
|     <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> | ||||
|  | ||||
| Accessing "clean" data | ||||
| ---------------------- | ||||
|  | ||||
|   | ||||
| @@ -127,6 +127,8 @@ We've specified ``auto_id=False`` to simplify the output:: | ||||
| The ``initial`` argument lets you specify the initial value to use when | ||||
| rendering this ``Field`` in an unbound ``Form``. | ||||
|  | ||||
| To specify dynamic initial data, see the :attr:`Form.initial` parameter. | ||||
|  | ||||
| The use-case for this is when you want to display an "empty" form in which a | ||||
| field is initialized to a particular value. For example:: | ||||
|  | ||||
| @@ -234,7 +236,6 @@ fields. We've specified ``auto_id=False`` to simplify the output:: | ||||
|  | ||||
| .. attribute:: Field.error_messages | ||||
|  | ||||
|  | ||||
| The ``error_messages`` argument lets you override the default messages that the | ||||
| field will raise. Pass in a dictionary with keys matching the error messages you | ||||
| want to override. For example, here is the default error message:: | ||||
| @@ -256,54 +257,6 @@ And here is a custom error message:: | ||||
| In the `built-in Field classes`_ section below, each ``Field`` defines the | ||||
| error message keys it uses. | ||||
|  | ||||
| Dynamic initial values | ||||
| ---------------------- | ||||
|  | ||||
| The ``initial`` argument to ``Field`` (explained above) lets you hard-code the | ||||
| initial value for a ``Field`` -- but what if you want to declare the initial | ||||
| value at runtime? For example, you might want to fill in a ``username`` field | ||||
| with the username of the current session. | ||||
|  | ||||
| To accomplish this, use the ``initial`` argument to a ``Form``. This argument, | ||||
| if given, should be a dictionary mapping field names to initial values. Only | ||||
| include the fields for which you're specifying an initial value; it's not | ||||
| necessary to include every field in your form. For example:: | ||||
|  | ||||
|     >>> class CommentForm(forms.Form): | ||||
|     ...     name = forms.CharField() | ||||
|     ...     url = forms.URLField() | ||||
|     ...     comment = forms.CharField() | ||||
|     >>> f = CommentForm(initial={'name': 'your username'}, auto_id=False) | ||||
|     >>> print f | ||||
|     <tr><th>Name:</th><td><input type="text" name="name" value="your username" /></td></tr> | ||||
|     <tr><th>Url:</th><td><input type="text" name="url" /></td></tr> | ||||
|     <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> | ||||
|     >>> f = CommentForm(initial={'name': 'another username'}, auto_id=False) | ||||
|     >>> print f | ||||
|     <tr><th>Name:</th><td><input type="text" name="name" value="another username" /></td></tr> | ||||
|     <tr><th>Url:</th><td><input type="text" name="url" /></td></tr> | ||||
|     <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> | ||||
|  | ||||
| Just like the ``initial`` parameter to ``Field``, these values are only | ||||
| displayed for unbound forms, and they're not used as fallback values if a | ||||
| particular value isn't provided. | ||||
|  | ||||
| Finally, note that if a ``Field`` defines ``initial`` *and* you include | ||||
| ``initial`` when instantiating the ``Form``, then the latter ``initial`` will | ||||
| have precedence. In this example, ``initial`` is provided both at the field | ||||
| level and at the form instance level, and the latter gets precedence:: | ||||
|  | ||||
|     >>> class CommentForm(forms.Form): | ||||
|     ...     name = forms.CharField(initial='class') | ||||
|     ...     url = forms.URLField() | ||||
|     ...     comment = forms.CharField() | ||||
|     >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False) | ||||
|     >>> print f | ||||
|     <tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr> | ||||
|     <tr><th>Url:</th><td><input type="text" name="url" /></td></tr> | ||||
|     <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> | ||||
|  | ||||
|  | ||||
| Built-in ``Field`` classes | ||||
| -------------------------- | ||||
|  | ||||
| @@ -819,6 +772,20 @@ example:: | ||||
|         def label_from_instance(self, obj): | ||||
|             return "My Object #%i" % obj.id | ||||
|  | ||||
| .. attribute:: ModelChoiceField.empty_label | ||||
|  | ||||
|    By default the ``<select>`` widget used by ``ModelChoiceField`` will have a | ||||
|    an empty choice at the top of the list. You can change the text of this label | ||||
|    (which is ``"---------"`` by default) with the ``empty_label`` attribute, or | ||||
|    you can disable the empty label entirely by setting ``empty_label`` to | ||||
|    ``None``:: | ||||
|     | ||||
|         # A custom empty label | ||||
|         field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)") | ||||
|          | ||||
|         # No empty label | ||||
|         field2 = forms.ModelChoiceField(queryset=..., empty_label=None) | ||||
|  | ||||
| ``ModelMultipleChoiceField`` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
|   | ||||
| @@ -62,7 +62,8 @@ commonly used groups of widgets: | ||||
|      | ||||
|         The format in which this field's initial value will be displayed. | ||||
|      | ||||
|     If no ``format`` argument is provided, the default format is ``'%Y-%m-%d %H:%M:%S'``. | ||||
|     If no ``format`` argument is provided, the default format is ``'%Y-%m-%d | ||||
|     %H:%M:%S'``. | ||||
|  | ||||
| .. class:: TimeInput | ||||
|  | ||||
| @@ -90,6 +91,8 @@ commonly used groups of widgets: | ||||
| .. class:: Select | ||||
|  | ||||
|     Select widget: ``<select><option ...>...</select>`` | ||||
|      | ||||
|     Requires that your field provides :attr:`~Field.choices`. | ||||
|  | ||||
| .. class:: NullBooleanSelect | ||||
|  | ||||
| @@ -100,6 +103,8 @@ commonly used groups of widgets: | ||||
|     Select widget allowing multiple selection: ``<select | ||||
|     multiple='multiple'>...</select>`` | ||||
|  | ||||
|     Requires that your field provides :attr:`~Field.choices`. | ||||
|  | ||||
| .. class:: RadioSelect | ||||
|  | ||||
|     A list of radio buttons: | ||||
| @@ -110,6 +115,8 @@ commonly used groups of widgets: | ||||
|           <li><input type='radio' ...></li> | ||||
|           ... | ||||
|         </ul> | ||||
|          | ||||
|     Requires that your field provides :attr:`~Field.choices`. | ||||
|  | ||||
| .. class:: CheckboxSelectMultiple | ||||
|  | ||||
|   | ||||
| @@ -870,11 +870,11 @@ the model is related. This works exactly the same as it does for | ||||
| Behind the scenes, Django creates an intermediary join table to represent the | ||||
| many-to-many relationship. By default, this table name is generated using the | ||||
| names of the two tables being joined. Since some databases don't support table | ||||
| names above a certain length (often 32 characters), these table names will be | ||||
| automatically truncated to 32 characters and a uniqueness hash will be used. | ||||
| This means you might see table names like ``author_books_9cdf4``; this is | ||||
| perfectly normal. You can manually provide the name of the join table using | ||||
| the :attr:`~ManyToManyField.db_table` option. | ||||
| names above a certain length, these table names will be automatically | ||||
| truncated to 64 characters and a uniqueness hash will be used. This means you | ||||
| might see table names like ``author_books_9cdf4``; this is perfectly normal. | ||||
| You can manually provide the name of the join table using the | ||||
| :attr:`~ManyToManyField.db_table` option. | ||||
|  | ||||
| .. _manytomany-arguments: | ||||
|  | ||||
| @@ -889,8 +889,9 @@ that control how the relationship functions. | ||||
|  | ||||
|     Same as :attr:`ForeignKey.limit_choices_to`. | ||||
|  | ||||
|     ``limit_choices_to`` has no effect when used on a ``ManyToManyField`` with | ||||
|     an intermediate table. | ||||
|     ``limit_choices_to`` has no effect when used on a ``ManyToManyField`` with a | ||||
|     custom intermediate table specified using the | ||||
|     :attr:`~ManyToManyField.through` paramter. | ||||
|  | ||||
| .. attribute:: ManyToManyField.symmetrical | ||||
|  | ||||
| @@ -920,7 +921,8 @@ that control how the relationship functions. | ||||
|     use. | ||||
|  | ||||
|     The most common use for this option is when you want to associate | ||||
|     :ref:`extra data with a many-to-many relationship <intermediary-manytomany>`. | ||||
|     :ref:`extra data with a many-to-many relationship | ||||
|     <intermediary-manytomany>`. | ||||
|  | ||||
| .. attribute:: ManyToManyField.db_table | ||||
|  | ||||
|   | ||||
| @@ -188,6 +188,18 @@ almost always do the right thing and trying to override that will lead to | ||||
| errors that are difficult to track down. This feature is for advanced use | ||||
| only. | ||||
|  | ||||
| Deleting objects | ||||
| ================ | ||||
|  | ||||
| .. method:: Model.delete() | ||||
|  | ||||
|    Issues a SQL ``DELETE`` for the object. This only deletes the object in the | ||||
|    database; the Python instance will still be around, and will still have data | ||||
|    in its fields. | ||||
|     | ||||
|    For more details, including how to delete objects in bulk, see | ||||
|    :ref:`topics-db-queries-delete`. | ||||
|  | ||||
| .. _model-instance-methods: | ||||
|  | ||||
| Other model instance methods | ||||
|   | ||||
| @@ -4,11 +4,32 @@ | ||||
| Related objects reference | ||||
| ========================= | ||||
|  | ||||
| Extra methods on managers when used in a ForeignKey context | ||||
| =========================================================== | ||||
|  | ||||
| .. currentmodule:: django.db.models | ||||
|  | ||||
| This document describes extra methods available on managers when used in a one-to-many or many-to-many related context. This happens in two cases: | ||||
|  | ||||
|     * The "other side" of a ``ForeignKey`` relation. That is:: | ||||
|      | ||||
|             class Reporter(models.Model): | ||||
|                 ... | ||||
|                  | ||||
|             class Article(models.Model): | ||||
|                 reporter = models.ForeignKey(Reporter) | ||||
|              | ||||
|       In the above example, the methods below will be available on | ||||
|       the manager ``reporter.article_set``. | ||||
|        | ||||
|     * Both sides of a ``ManyToManyField`` relation:: | ||||
|      | ||||
|             class Topping(models.Model): | ||||
|                 ... | ||||
|                  | ||||
|             class Pizza(models.Model): | ||||
|                 toppings = models.ManyToManyField(Topping) | ||||
|                  | ||||
|       In this example, the methods below will be available both on | ||||
|       ``topping.pizza_set`` and on ``pizza.toppings``. | ||||
|  | ||||
| .. method:: QuerySet.add(obj1, [obj2, ...]) | ||||
|  | ||||
|     Adds the specified model objects to the related object set. | ||||
|   | ||||
| @@ -323,7 +323,7 @@ optional, third positional argument, ``processors``. In this example, the | ||||
|         c = RequestContext(request, { | ||||
|             'foo': 'bar', | ||||
|         }, [ip_address_processor]) | ||||
|         return t.render(c) | ||||
|         return HttpResponse(t.render(c)) | ||||
|  | ||||
| .. note:: | ||||
|     If you're using Django's ``render_to_response()`` shortcut to populate a | ||||
| @@ -519,18 +519,19 @@ By default, Django uses a filesystem-based template loader, but Django comes | ||||
| with a few other template loaders, which know how to load templates from other | ||||
| sources. | ||||
|  | ||||
| These other loaders are disabled by default, but you can activate them by | ||||
| editing your :setting:`TEMPLATE_LOADERS` setting. :setting:`TEMPLATE_LOADERS` | ||||
| Some of these other loaders are disabled by default, but you can activate them | ||||
| by editing your :setting:`TEMPLATE_LOADERS` setting. :setting:`TEMPLATE_LOADERS` | ||||
| should be a tuple of strings, where each string represents a template loader. | ||||
| Here are the template loaders that come with Django: | ||||
|  | ||||
| ``django.template.loaders.filesystem.load_template_source`` | ||||
|     Loads templates from the filesystem, according to :setting:`TEMPLATE_DIRS`. | ||||
|     This loader is enabled by default. | ||||
|  | ||||
| ``django.template.loaders.app_directories.load_template_source`` | ||||
|     Loads templates from Django apps on the filesystem. For each app in | ||||
|     :setting:`INSTALLED_APPS`, the loader looks for a ``templates`` subdirectory. If | ||||
|     the directory exists, Django looks for templates in there. | ||||
|     :setting:`INSTALLED_APPS`, the loader looks for a ``templates`` | ||||
|     subdirectory. If the directory exists, Django looks for templates in there. | ||||
|  | ||||
|     This means you can store templates with your individual apps. This also | ||||
|     makes it easy to distribute Django apps with default templates. | ||||
| @@ -545,16 +546,21 @@ Here are the template loaders that come with Django: | ||||
|         * ``/path/to/myproject/polls/templates/foo.html`` | ||||
|         * ``/path/to/myproject/music/templates/foo.html`` | ||||
|  | ||||
|     Note that the loader performs an optimization when it is first imported: | ||||
|     It caches a list of which :setting:`INSTALLED_APPS` packages have a ``templates`` | ||||
|     subdirectory. | ||||
|     Note that the loader performs an optimization when it is first imported: It | ||||
|     caches a list of which :setting:`INSTALLED_APPS` packages have a | ||||
|     ``templates`` subdirectory. | ||||
|      | ||||
|     This loader is enabled by default. | ||||
|  | ||||
| ``django.template.loaders.eggs.load_template_source`` | ||||
|     Just like ``app_directories`` above, but it loads templates from Python | ||||
|     eggs rather than from the filesystem. | ||||
|      | ||||
|     This loader is disabled by default. | ||||
|  | ||||
| Django uses the template loaders in order according to the :setting:`TEMPLATE_LOADERS` | ||||
| setting. It uses each loader until a loader finds a match. | ||||
| Django uses the template loaders in order according to the | ||||
| :setting:`TEMPLATE_LOADERS` setting. It uses each loader until a loader finds a | ||||
| match. | ||||
|  | ||||
| The ``render_to_string()`` shortcut | ||||
| =================================== | ||||
|   | ||||
| @@ -273,7 +273,7 @@ You can pass either Unicode strings or UTF-8 bytestrings as arguments to | ||||
| querysets are identical:: | ||||
|  | ||||
|     qs = People.objects.filter(name__contains=u'Å') | ||||
|     qs = People.objects.filter(name__contains='\xc3\85') # UTF-8 encoding of Å | ||||
|     qs = People.objects.filter(name__contains='\xc3\x85') # UTF-8 encoding of Å | ||||
|  | ||||
| Templates | ||||
| ========= | ||||
|   | ||||
| @@ -74,6 +74,14 @@ break anything if you leave them, but they also won't do anything. To register | ||||
| apps with the admin you'll move those declarations to an ``admin.py`` file; | ||||
| see `the admin`_ below for more details. | ||||
|  | ||||
| .. seealso:: | ||||
|  | ||||
|     A contributor to djangosnippets__ has written a script that'll `scan your | ||||
|     models.py and generate a corresponding admin.py`__. | ||||
|  | ||||
|     __ http://www.djangosnippets.org/ | ||||
|     __ http://www.djangosnippets.org/snippets/603/ | ||||
|  | ||||
| Example | ||||
| ~~~~~~~ | ||||
|  | ||||
| @@ -121,7 +129,7 @@ The Admin | ||||
| One of the biggest changes in 1.0 is the new admin. The Django administrative | ||||
| interface (``django.contrib.admin``) has been completely refactored; admin | ||||
| definitions are now completely decoupled from model definitions, the framework | ||||
| as been rewritten to use Django's new form-handling library and redesigned with | ||||
| has been rewritten to use Django's new form-handling library and redesigned with | ||||
| extensibility and customization in mind. | ||||
|  | ||||
| Practically, this means you'll need to rewrite all of your ``class Admin`` | ||||
| @@ -130,14 +138,6 @@ Admin`` with a ``admin.site.register()`` call in an ``admin.py`` file. Below are | ||||
| some more details on how to rewrite that ``Admin`` declaration into the new | ||||
| syntax. | ||||
|  | ||||
| .. seealso:: | ||||
|  | ||||
|     A contributor to djangosnippets__ has written a script that'll `scan your | ||||
|     models.py and generate a corresponding admin.py`__. | ||||
|  | ||||
|     __ http://www.djangosnippets.org/ | ||||
|     __ http://www.djangosnippets.org/snippets/603/ | ||||
|  | ||||
| Use new inline syntax | ||||
| ~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| @@ -320,6 +320,11 @@ Note that the ``width`` and ``height`` attributes only make sense for | ||||
| :class:`~django.db.models.ImageField` fields. More details can be found in the | ||||
| :ref:`model API <ref-models-fields>` documentation. | ||||
|  | ||||
| Use ``Paginator`` instead of ``ObjectPaginator`` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| The ``ObjectPaginator`` in 0.96 has been removed and replaced with an improved | ||||
| version, :class:`django.core.paginator.Paginator`. | ||||
|  | ||||
| Templates | ||||
| --------- | ||||
|   | ||||
| @@ -208,9 +208,9 @@ Methods | ||||
|  | ||||
|     .. method:: models.User.has_perm(perm) | ||||
|  | ||||
|         Returns ``True`` if the user has the specified permission, where perm | ||||
|         is in the format ``"package.codename"``. If the user is inactive, this | ||||
|         method will always return ``False``. | ||||
|         Returns ``True`` if the user has the specified permission, where perm is | ||||
|         in the format ``"<application name>.<lowercased model name>"``. If the | ||||
|         user is inactive, this method will always return ``False``. | ||||
|  | ||||
|     .. method:: models.User.has_perms(perm_list) | ||||
|  | ||||
| @@ -444,18 +444,18 @@ To indicate that this model is the user profile model for a given site, fill in | ||||
| the setting :setting:`AUTH_PROFILE_MODULE` with a string consisting of the | ||||
| following items, separated by a dot: | ||||
|  | ||||
| 1. The (normalized to lower-case) name of the application in which the user | ||||
|    profile model is defined (in other words, an all-lowercase version of the | ||||
| 1. The name of the application (case sensitive) in which the user | ||||
|    profile model is defined (in other words, the | ||||
|    name which was passed to :djadmin:`manage.py startapp <startapp>` to create | ||||
|    the application). | ||||
|  | ||||
| 2. The (normalized to lower-case) name of the model class. | ||||
| 2. The name of the model (not case sensitive) class. | ||||
|  | ||||
| For example, if the profile model was a class named ``UserProfile`` and was | ||||
| defined inside an application named ``accounts``, the appropriate setting would | ||||
| be:: | ||||
|  | ||||
|     AUTH_PROFILE_MODULE = 'accounts.userprofile' | ||||
|     AUTH_PROFILE_MODULE = 'accounts.UserProfile' | ||||
|  | ||||
| When a user profile model has been defined and specified in this manner, each | ||||
| :class:`~django.contrib.auth.models.User` object will have a method -- | ||||
| @@ -779,7 +779,7 @@ In addition to the :func:`~views.login` view, the authentication system | ||||
| includes a few other useful built-in views located in | ||||
| :mod:`django.contrib.auth.views`: | ||||
|  | ||||
| .. function:: views.logout(request, [next_page, template_name]) | ||||
| .. function:: views.logout(request, [next_page, template_name, redirect_field_name]) | ||||
|  | ||||
|     Logs a user out. | ||||
|  | ||||
| @@ -790,6 +790,10 @@ includes a few other useful built-in views located in | ||||
|         * ``template_name``: The full name of a template to display after | ||||
|           logging the user out. This will default to | ||||
|           :file:`registration/logged_out.html` if no argument is supplied. | ||||
|            | ||||
|         * ``redirect_field_name``: The name of a ``GET`` field containing the | ||||
|           URL to redirect to after log out. Overrides ``next_page`` if the given | ||||
|           ``GET`` parameter is passed. | ||||
|  | ||||
|     **Template context:** | ||||
|  | ||||
| @@ -1017,6 +1021,10 @@ The permission_required decorator | ||||
|             # ... | ||||
|         my_view = permission_required('polls.can_vote')(my_view) | ||||
|  | ||||
|     As for the :meth:`User.has_perm` method, permission names take the form | ||||
|     ``"<application name>.<lowercased model name>"`` (i.e. ``polls.choice`` for | ||||
|     a ``Choice`` model in the ``polls`` application). | ||||
|  | ||||
|     Note that :func:`~django.contrib.auth.decorators.permission_required()` | ||||
|     also takes an optional ``login_url`` parameter. Example:: | ||||
|  | ||||
| @@ -1332,6 +1340,16 @@ The order of :setting:`AUTHENTICATION_BACKENDS` matters, so if the same | ||||
| username and password is valid in multiple backends, Django will stop | ||||
| processing at the first positive match. | ||||
|  | ||||
| .. note:: | ||||
|  | ||||
|     Once a user has authenticated, Django stores which backend was used to | ||||
|     authenticate the user in the user's session, and re-uses the same backend | ||||
|     for subsequent authentication attempts for that user. This effectively means | ||||
|     that authentication sources are cached, so if you change | ||||
|     :setting:`AUTHENTICATION_BACKENDS`, you'll need to clear out session data if | ||||
|     you need to force users to re-authenticate using different methods. A simple | ||||
|     way to do that is simply to execute ``Session.objects.all().delete()``. | ||||
|  | ||||
| Writing an authentication backend | ||||
| --------------------------------- | ||||
|  | ||||
|   | ||||
| @@ -234,12 +234,12 @@ the ``CACHE_BACKEND`` setting. Valid arguments are as follows: | ||||
|       backends, the maximum number of entries allowed in the cache before old | ||||
|       values are deleted. This argument defaults to 300. | ||||
|  | ||||
|     * ``cull_percentage``: The percentage of entries that are culled when | ||||
|       ``max_entries`` is reached. The actual ratio is ``1/cull_percentage``, so | ||||
|       set ``cull_percentage=2`` to cull half of the entries when ``max_entries`` | ||||
|     * ``cull_frequency``: The fraction of entries that are culled when | ||||
|       ``max_entries`` is reached. The actual ratio is ``1/cull_frequency``, so | ||||
|       set ``cull_frequency=2`` to cull half of the entries when ``max_entries`` | ||||
|       is reached. | ||||
|  | ||||
|       A value of ``0`` for ``cull_percentage`` means that the entire cache will | ||||
|       A value of ``0`` for ``cull_frequency`` means that the entire cache will | ||||
|       be dumped when ``max_entries`` is reached. This makes culling *much* | ||||
|       faster at the expense of more cache misses. | ||||
|  | ||||
|   | ||||
| @@ -165,12 +165,37 @@ ones: | ||||
|         A choices list looks like this:: | ||||
|  | ||||
|             YEAR_IN_SCHOOL_CHOICES = ( | ||||
|                 ('FR', 'Freshman'), | ||||
|                 ('SO', 'Sophomore'), | ||||
|                 ('JR', 'Junior'), | ||||
|                 ('SR', 'Senior'), | ||||
|                 ('GR', 'Graduate'), | ||||
|                 (u'FR', u'Freshman'), | ||||
|                 (u'SO', u'Sophomore'), | ||||
|                 (u'JR', u'Junior'), | ||||
|                 (u'SR', u'Senior'), | ||||
|                 (u'GR', u'Graduate'), | ||||
|             ) | ||||
|          | ||||
|         The first element in each tuple is the value that will be stored in the | ||||
|         database, the second element will be displayed by the admin interface, | ||||
|         or in a ModelChoiceField. Given an instance of a model object, the | ||||
|         display value for a choices field can be accessed using the | ||||
|         ``get_FOO_display`` method. For example:: | ||||
|          | ||||
|             from django.db import models | ||||
|              | ||||
|             class Person(models.Model): | ||||
|                 GENDER_CHOICES = ( | ||||
|                     (u'M', u'Male'), | ||||
|                     (u'F', u'Female'), | ||||
|                 ) | ||||
|                 name = models.CharField(max_length=60) | ||||
|                 gender = models.CharField(max_length=2, choices=GENDER_CHOICES) | ||||
|          | ||||
|         :: | ||||
|          | ||||
|             >>> p = Person(name="Fred Flinstone", gender="M") | ||||
|             >>> p.save() | ||||
|             >>> p.gender | ||||
|             u'M' | ||||
|             >>> p.get_gender_display() | ||||
|             u'Male' | ||||
|  | ||||
|     :attr:`~Field.default` | ||||
|         The default value for the field. This can be a value or a callable | ||||
|   | ||||
| @@ -267,9 +267,9 @@ of all the various ``QuerySet`` methods. | ||||
| Limiting QuerySets | ||||
| ------------------ | ||||
|  | ||||
| Use Python's array-slicing syntax to limit your ``QuerySet`` to a certain | ||||
| number of results. This is the equivalent of SQL's ``LIMIT`` and ``OFFSET`` | ||||
| clauses. | ||||
| Use a subset of Python's array-slicing syntax to limit your ``QuerySet`` to a | ||||
| certain number of results. This is the equivalent of SQL's ``LIMIT`` and | ||||
| ``OFFSET`` clauses. | ||||
|  | ||||
| For example, this returns the first 5 objects (``LIMIT 5``):: | ||||
|  | ||||
| @@ -278,6 +278,9 @@ For example, this returns the first 5 objects (``LIMIT 5``):: | ||||
| This returns the sixth through tenth objects (``OFFSET 5 LIMIT 5``):: | ||||
|  | ||||
|     >>> Entry.objects.all()[5:10] | ||||
|      | ||||
| Negative indexing (i.e. ``Entry.objects.all()[-1]``) is not supported, nor is | ||||
| the third "step" slice parameter. | ||||
|  | ||||
| Generally, slicing a ``QuerySet`` returns a new ``QuerySet`` -- it doesn't | ||||
| evaluate the query. An exception is if you use the "step" parameter of Python | ||||
|   | ||||
| @@ -310,7 +310,9 @@ Using a formset in views and templates | ||||
|  | ||||
| Using a formset inside a view is as easy as using a regular ``Form`` class. | ||||
| The only thing you will want to be aware of is making sure to use the | ||||
| management form inside the template. Lets look at a sample view:: | ||||
| management form inside the template. Let's look at a sample view: | ||||
|  | ||||
| .. code-block:: python | ||||
|  | ||||
|     def manage_articles(request): | ||||
|         ArticleFormSet = formset_factory(ArticleForm) | ||||
| @@ -355,7 +357,9 @@ You are able to use more than one formset in a view if you like. Formsets | ||||
| borrow much of its behavior from forms. With that said you are able to use | ||||
| ``prefix`` to prefix formset form field names with a given value to allow | ||||
| more than one formset to be sent to a view without name clashing. Lets take | ||||
| a look at how this might be accomplished:: | ||||
| a look at how this might be accomplished: | ||||
|  | ||||
| .. code-block:: python | ||||
|  | ||||
|     def manage_articles(request): | ||||
|         ArticleFormSet = formset_factory(ArticleForm) | ||||
|   | ||||
| @@ -45,35 +45,62 @@ the full list of conversions: | ||||
|     Model field                      Form field | ||||
|     ===============================  ======================================== | ||||
|     ``AutoField``                    Not represented in the form | ||||
|      | ||||
|     ``BooleanField``                 ``BooleanField`` | ||||
|      | ||||
|     ``CharField``                    ``CharField`` with ``max_length`` set to | ||||
|                                      the model field's ``max_length`` | ||||
|      | ||||
|     ``CommaSeparatedIntegerField``   ``CharField`` | ||||
|      | ||||
|     ``DateField``                    ``DateField`` | ||||
|      | ||||
|     ``DateTimeField``                ``DateTimeField`` | ||||
|      | ||||
|     ``DecimalField``                 ``DecimalField`` | ||||
|      | ||||
|     ``EmailField``                   ``EmailField`` | ||||
|      | ||||
|     ``FileField``                    ``FileField`` | ||||
|      | ||||
|     ``FilePathField``                ``CharField`` | ||||
|      | ||||
|     ``FloatField``                   ``FloatField`` | ||||
|      | ||||
|     ``ForeignKey``                   ``ModelChoiceField`` (see below) | ||||
|      | ||||
|     ``ImageField``                   ``ImageField`` | ||||
|      | ||||
|     ``IntegerField``                 ``IntegerField`` | ||||
|      | ||||
|     ``IPAddressField``               ``IPAddressField`` | ||||
|      | ||||
|     ``ManyToManyField``              ``ModelMultipleChoiceField`` (see | ||||
|                                      below) | ||||
|      | ||||
|     ``NullBooleanField``             ``CharField`` | ||||
|      | ||||
|     ``PhoneNumberField``             ``USPhoneNumberField`` | ||||
|                                      (from ``django.contrib.localflavor.us``) | ||||
|      | ||||
|     ``PositiveIntegerField``         ``IntegerField`` | ||||
|      | ||||
|     ``PositiveSmallIntegerField``    ``IntegerField`` | ||||
|      | ||||
|     ``SlugField``                    ``SlugField`` | ||||
|      | ||||
|     ``SmallIntegerField``            ``IntegerField`` | ||||
|     ``TextField``                    ``CharField`` with ``widget=Textarea`` | ||||
|      | ||||
|     ``TextField``                    ``CharField`` with  | ||||
|                                      ``widget=forms.Textarea`` | ||||
|      | ||||
|     ``TimeField``                    ``TimeField`` | ||||
|      | ||||
|     ``URLField``                     ``URLField`` with ``verify_exists`` set | ||||
|                                      to the model field's ``verify_exists`` | ||||
|     ``XMLField``                     ``CharField`` with ``widget=Textarea`` | ||||
|      | ||||
|     ``XMLField``                     ``CharField`` with  | ||||
|                                      ``widget=forms.Textarea`` | ||||
|     ===============================  ======================================== | ||||
|  | ||||
|  | ||||
| @@ -458,14 +485,15 @@ queryset that includes all objects in the model (e.g., | ||||
|  | ||||
|     >>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O')) | ||||
|  | ||||
| Alternatively, you can create a subclass that implements a ``get_queryset()`` | ||||
| method:: | ||||
|  | ||||
| Alternatively, you can create a subclass that sets ``self.queryset`` in | ||||
| ``__init__``:: | ||||
|      | ||||
|     from django.forms.models import BaseModelFormSet | ||||
|  | ||||
|     class BaseAuthorFormSet(BaseModelFormSet): | ||||
|         def get_queryset(self): | ||||
|             return super(BaseAuthorFormSet, self).get_queryset().filter(name__startswith='O') | ||||
|         def __init__(self, *args, **kwargs): | ||||
|             self.queryset = Author.objects.filter(name__startswith='O') | ||||
|             super(BaseAuthorFormSet, self).__init__(*args, **kwargs) | ||||
|  | ||||
| Then, pass your ``BaseAuthorFormSet`` class to the factory function:: | ||||
|  | ||||
|   | ||||
| @@ -111,6 +111,12 @@ middleware is always called on every response. | ||||
| object. It could alter the given ``response``, or it could create and return a | ||||
| brand-new :class:`~django.http. HttpResponse`. | ||||
|  | ||||
| Remember that your middleware will not be called if another middleware object | ||||
| returns a response before you. But unlike ``process_request()`` and | ||||
| ``process_view()``, during the response phase the classes are applied in reverse | ||||
| order, from the bottom up. This means classes defined at the end of | ||||
| :setting:`MIDDLEWARE_CLASSES` will be run first. | ||||
|  | ||||
| .. _exception-middleware: | ||||
|  | ||||
| ``process_exception`` | ||||
| @@ -127,6 +133,10 @@ Django calls ``process_exception()`` when a view raises an exception. | ||||
| :class:`~django.http. HttpResponse` object, the response will be returned to | ||||
| the browser. Otherwise, default exception handling kicks in. | ||||
|  | ||||
| Again, middleware are run in reverse order during the response phase, which | ||||
| includes ``process_exception``. If an exception middleware return a response, | ||||
| the middleware classes above that middleware will not be called at all. | ||||
|  | ||||
| ``__init__`` | ||||
| ------------ | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,11 @@ objects into other formats. Usually these other formats will be text-based and | ||||
| used for sending Django objects over a wire, but it's possible for a | ||||
| serializer to handle any format (text-based or not). | ||||
|  | ||||
| .. seealso:: | ||||
|  | ||||
|     If you just want to get some data from your tables into a serialized | ||||
|     form, you could use the :djadmin:`dumpdata` management command. | ||||
|  | ||||
| Serializing data | ||||
| ---------------- | ||||
|  | ||||
|   | ||||
| @@ -944,9 +944,10 @@ See the :djadmin:`dumpdata documentation<dumpdata>` for more details. | ||||
|     Fixtures with other names can always be installed manually using the | ||||
|     ``manage.py loaddata`` command. | ||||
|  | ||||
| Once you've created a fixture and placed it somewhere in your Django project, | ||||
| you can use it in your unit tests by specifying a ``fixtures`` class attribute | ||||
| on your ``django.test.TestCase`` subclass:: | ||||
| Once you've created a fixture and placed it in a ``fixtures`` directory in one | ||||
| of your :setting:`INSTALLED_APPS`, you can use it in your unit tests by | ||||
| specifying a ``fixtures`` class attribute on your ``django.test.TestCase`` | ||||
| subclass:: | ||||
|  | ||||
|     from django.test import TestCase | ||||
|     from myapp.models import Animal | ||||
|   | ||||