From 0cf7bc439129c66df8d64601e885f83b256b4f25 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Wed, 27 Dec 2006 02:49:28 +0000 Subject: per-object-permissions: Merged to trunk [4241] git-svn-id: http://code.djangoproject.com/svn/django/branches/per-object-permissions@4242 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- docs/add_ons.txt | 17 +++ docs/contributing.txt | 109 ++++++++++++++++-- docs/csrf.txt | 37 +++--- docs/db-api.txt | 6 +- docs/forms.txt | 40 ++++--- docs/generic_views.txt | 4 +- docs/newforms.txt | 300 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/redirects.txt | 4 +- docs/sessions.txt | 2 +- docs/settings.txt | 4 +- docs/testing.txt | 2 +- 11 files changed, 473 insertions(+), 52 deletions(-) create mode 100644 docs/newforms.txt (limited to 'docs') diff --git a/docs/add_ons.txt b/docs/add_ons.txt index a0377700d7..58c01c4fc0 100644 --- a/docs/add_ons.txt +++ b/docs/add_ons.txt @@ -48,6 +48,23 @@ See the `csrf documentation`_. .. _csrf documentation: http://www.djangoproject.com/documentation/csrf/ +formtools +========= + +**New in Django development version** + +A set of high-level abstractions for Django forms (django.newforms). + +django.contrib.formtools.preview +-------------------------------- + +An abstraction of the following workflow: + +"Display an HTML form, force a preview, then do something with the submission." + +Full documentation for this feature does not yet exist, but you can read the +code and docstrings in ``django/contrib/formtools/preview.py`` for a start. + humanize ======== diff --git a/docs/contributing.txt b/docs/contributing.txt index 6ff0b038a3..de9236f6c1 100644 --- a/docs/contributing.txt +++ b/docs/contributing.txt @@ -22,6 +22,9 @@ of the community, so there are many ways you can help Django's development: likely to be skeptical of large-scale suggestions without some code to back it up. + * Triage patches that have been submitted by other users. Please read + `Ticket triage`_ below, for details on the triage process. + That's all you need to know if you'd like to join the Django development community. The rest of this document describes the details of how our community works and how it handles bugs, mailing lists, and all the other minutiae of @@ -44,8 +47,10 @@ particular: * **Do** write complete, reproducible, specific bug reports. Include as much information as you possibly can, complete with code snippets, test - cases, etc. A minimal example that illustrates the bug in a nice small - test case is the best possible bug report. + cases, etc. This means including a clear, concise description of the + problem, and a clear set of instructions for replicating the problem. + A minimal example that illustrates the bug in a nice small test case + is the best possible bug report. * **Don't** use the ticket system to ask support questions. Use the `django-users`_ list, or the `#django`_ IRC channel for that. @@ -121,6 +126,50 @@ Patch style it obvious that the ticket includes a patch, and it will add the ticket to the `list of tickets with patches`_. + * The code required to fix a problem or add a feature is an essential part + of a patch, but it is not the only part. A good patch should also include + a regression test to validate the behavior that has been fixed (and prevent + the problem from arising again). + + * If the code associated with a patch adds a new feature, or modifies behavior + of an existing feature, the patch should also contain documentation. + +Non-trivial patches +------------------- + +A "non-trivial" patch is one that is more than a simple bug fix. It's a patch +that introduces Django functionality and makes some sort of design decision. + +If you provide a non-trivial patch, include evidence that alternatives have +been discussed on `django-developers`_. If you're not sure whether your patch +should be considered non-trivial, just ask. + +Ticket triage +============= + +Unfortunately, not all bug reports in the `ticket tracker`_ provide all +the `required details`_. A number of tickets have patches, but those patches +don't meet all the requirements of a `good patch`_. + +One way to help out is to *triage* bugs that have been reported by other users. +Pick an open ticket that is missing some details, and try to replicate the +problem. Fill in the missing pieces of the report. If the ticket doesn't have +a patch, create one. + +Once you've completed all the missing details on the ticket and you have a +patch with all the required features, e-mail `django-developers`_. Indicate +that you have triaged a ticket, and recommend a course of action for dealing +with that ticket. + +At first, this may require you to be persistent. If you find that your triaged +ticket still isn't getting attention, occasional polite requests for eyeballs +to look at your ticket may be necessary. However, as you earn a reputation for +quality triage work, you should find that it is easier to get the developers' +attention. + +.. _required details: `Reporting bugs`_ +.. _good patch: `Patch style`_ + Submitting and maintaining translations ======================================= @@ -338,21 +387,63 @@ trunk more than once. Using branches -------------- -To test a given branch, you can simply check out the entire branch, like so:: +To use a branch, you'll need to do two things: + + * Get the branch's code through Subversion. + + * Point your Python ``site-packages`` directory at the branch's version of + the ``django`` package rather than the version you already have + installed. + +Getting the code from Subversion +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To get the latest version of a branch's code, check it out using Subversion:: svn co http://code.djangoproject.com/svn/django/branches// -Or, if you've got a working directory you'd like to switch to use a branch, -you can use:: +...where ```` is the branch's name. See the `list of branch names`_. - svn switch http://code.djangoproject.com/svn/django/branches// +Alternatively, you can automatically convert an existing directory of the +Django source code as long as you've checked it out via Subversion. To do the +conversion, execute this command from within your ``django`` directory:: -...in the root of your Django sandbox (the directory that contains ``django``, -``docs``, and ``tests``). + svn switch http://code.djangoproject.com/svn/django/branches// The advantage of using ``svn switch`` instead of ``svn co`` is that the ``switch`` command retains any changes you might have made to your local copy -of the code. It attempts to merge those changes into the "switched" code. +of the code. It attempts to merge those changes into the "switched" code. The +disadvantage is that it may cause conflicts with your local changes if the +"switched" code has altered the same lines of code. + +(Note that if you use ``svn switch``, you don't need to point Python at the new +version, as explained in the next section.) + +.. _list of branch names: http://code.djangoproject.com/browser/django/branches + +Pointing Python at the new Django version +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once you've retrieved the branch's code, you'll need to change your Python +``site-packages`` directory so that it points to the branch version of the +``django`` directory. (The ``site-packages`` directory is somewhere such as +``/usr/lib/python2.4/site-packages`` or +``/usr/local/lib/python2.4/site-packages`` or ``C:\Python\site-packages``.) + +The simplest way to do this is by renaming the old ``django`` directory to +``django.OLD`` and moving the trunk version of the code into the directory +and calling it ``django``. + +Alternatively, you can use a symlink called ``django`` that points to the +location of the branch's ``django`` package. If you want to switch back, just +change the symlink to point to the old code. + +If you're using Django 0.95 or earlier and installed it using +``python setup.py install``, you'll have a directory called something like +``Django-0.95-py2.4.egg`` instead of ``django``. In this case, edit the file +``setuptools.pth`` and remove the line that references the Django ``.egg`` +file. Then copy the branch's version of the ``django`` directory into +``site-packages``. Official releases ================= diff --git a/docs/csrf.txt b/docs/csrf.txt index 218b43a61a..c12dd1d116 100644 --- a/docs/csrf.txt +++ b/docs/csrf.txt @@ -1,9 +1,9 @@ ===================================== -Cross Site Request Forgery Protection +Cross Site Request Forgery protection ===================================== -The CsrfMiddleware class provides easy-to-use protection against -`Cross Site Request Forgeries`_. This type of attack occurs when a malicious +The CsrfMiddleware class provides easy-to-use protection against +`Cross Site Request Forgeries`_. This type of attack occurs when a malicious web site creates a link or form button that is intended to perform some action on your web site, using the credentials of a logged-in user who is tricked into clicking on the link in their browser. @@ -12,12 +12,12 @@ The first defense against CSRF attacks is to ensure that GET requests are side-effect free. POST requests can then be protected by adding this middleware into your list of installed middleware. - .. _Cross Site Request Forgeries: http://www.squarefree.com/securitytips/web-developers.html#CSRF How to use it ============= -Add the middleware ``'django.contrib.csrf.middleware.CsrfMiddleware'`` to + +Add the middleware ``'django.contrib.csrf.middleware.CsrfMiddleware'`` to your list of middleware classes, ``MIDDLEWARE_CLASSES``. It needs to process the response after the SessionMiddleware, so must come before it in the list. It also must process the response before things like compression @@ -25,16 +25,17 @@ happen to the response, so it must come after GZipMiddleware in the list. How it works ============ + CsrfMiddleware does two things: -1. It modifies outgoing requests by adding a hidden form field to all - 'POST' forms, with the name 'csrfmiddlewaretoken' and a value which is - a hash of the session ID plus a secret. If there is no session ID set, - this modification of the response isn't done, so there is very little +1. It modifies outgoing requests by adding a hidden form field to all + 'POST' forms, with the name 'csrfmiddlewaretoken' and a value which is + a hash of the session ID plus a secret. If there is no session ID set, + this modification of the response isn't done, so there is very little performance penalty for those requests that don't have a session. -2. On all incoming POST requests that have the session cookie set, it - checks that the 'csrfmiddlewaretoken' is present and correct. If it +2. On all incoming POST requests that have the session cookie set, it + checks that the 'csrfmiddlewaretoken' is present and correct. If it isn't, the user will get a 403 error. This ensures that only forms that have originated from your web site @@ -43,26 +44,26 @@ 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. +request will always 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 could make these kind of requests anyway. -The Content-Type is checked before modifying the response, and only +The Content-Type is checked before modifying the response, and only pages that are served as 'text/html' or 'application/xml+xhtml' are modified. Limitations =========== + CsrfMiddleware requires Django's session framework to work. If you have a custom authentication system that manually sets cookies and the like, it won't help you. -If your app creates HTML pages and forms in some unusual way, (e.g. -it sends fragments of HTML in javascript document.write statements) -you might bypass the filter that adds the hidden field to the form, +If your app creates HTML pages and forms in some unusual way, (e.g. +it sends fragments of HTML in javascript document.write statements) +you might bypass the filter that adds the hidden field to the form, in which case form submission will always fail. It may still be possible to use the middleware, provided you can find some way to get the -CSRF token and ensure that is included when your form is submitted. - +CSRF token and ensure that is included when your form is submitted. \ No newline at end of file diff --git a/docs/db-api.txt b/docs/db-api.txt index 2f0c8b0589..13a32bd0b8 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -143,9 +143,9 @@ or ``UPDATE`` SQL statements. Specifically, when you call ``save()``, Django follows this algorithm: * If the object's primary key attribute is set to a value that evaluates to - ``False`` (such as ``None`` or the empty string), Django executes a - ``SELECT`` query to determine whether a record with the given primary key - already exists. + ``True`` (i.e., a value other than ``None`` or the empty string), Django + executes a ``SELECT`` query to determine whether a record with the given + primary key already exists. * If the record with the given primary key does already exist, Django executes an ``UPDATE`` query. * If the object's primary key attribute is *not* set, or if it's set but a diff --git a/docs/forms.txt b/docs/forms.txt index ff192a4717..6efa24d28f 100644 --- a/docs/forms.txt +++ b/docs/forms.txt @@ -2,15 +2,27 @@ Forms, fields, and manipulators =============================== +Forwards-compatibility note +=========================== + +The legacy forms/manipulators system described in this document is going to be +replaced in the next Django release. If you're starting from scratch, we +strongly encourage you not to waste your time learning this. Instead, learn and +use the django.newforms system, which we have begun to document in the +`newforms documentation`_. + +If you have legacy form/manipulator code, read the "Migration plan" section in +that document to understand how we're making the switch. + +.. _newforms documentation: http://www.djangoproject.com/documentation/newforms/ + +Introduction +============ + Once you've got a chance to play with Django's admin interface, you'll probably wonder if the fantastic form validation framework it uses is available to user code. It is, and this document explains how the framework works. - .. admonition:: A note to the lazy - - If all you want to do is present forms for a user to create and/or - update a given object, you may be able to use `generic views`_. - We'll take a top-down approach to examining Django's form validation framework, because much of the time you won't need to use the lower-level APIs. Throughout this document, we'll be working with the following model, a "place" object:: @@ -41,17 +53,17 @@ this document, we'll be working with the following model, a "place" object:: Defining the above class is enough to create an admin interface to a ``Place``, but what if you want to allow public users to submit places? -Manipulators -============ +Automatic Manipulators +====================== The highest-level interface for object creation and modification is the -**Manipulator** framework. A manipulator is a utility class tied to a given -model that "knows" how to create or modify instances of that model and how to -validate data for the object. Manipulators come in two flavors: -``AddManipulators`` and ``ChangeManipulators``. Functionally they are quite -similar, but the former knows how to create new instances of the model, while -the latter modifies existing instances. Both types of classes are automatically -created when you define a new class:: +**automatic Manipulator** framework. An automatic manipulator is a utility +class tied to a given model that "knows" how to create or modify instances of +that model and how to validate data for the object. Automatic Manipulators come +in two flavors: ``AddManipulators`` and ``ChangeManipulators``. Functionally +they are quite similar, but the former knows how to create new instances of the +model, while the latter modifies existing instances. Both types of classes are +automatically created when you define a new class:: >>> from mysite.myapp.models import Place >>> Place.AddManipulator diff --git a/docs/generic_views.txt b/docs/generic_views.txt index 1736770a20..25635f35d8 100644 --- a/docs/generic_views.txt +++ b/docs/generic_views.txt @@ -902,7 +902,7 @@ If ``template_name`` isn't specified, this view will use the template In addition to ``extra_context``, the template's context will be: - * ``form``: A ``django.forms.FormWrapper`` instance representing the form + * ``form``: A ``django.oldforms.FormWrapper`` instance representing the form for editing the object. This lets you refer to form fields easily in the template system. @@ -984,7 +984,7 @@ If ``template_name`` isn't specified, this view will use the template In addition to ``extra_context``, the template's context will be: - * ``form``: A ``django.forms.FormWrapper`` instance representing the form + * ``form``: A ``django.oldforms.FormWrapper`` instance representing the form for editing the object. This lets you refer to form fields easily in the template system. diff --git a/docs/newforms.txt b/docs/newforms.txt new file mode 100644 index 0000000000..c4986eb45e --- /dev/null +++ b/docs/newforms.txt @@ -0,0 +1,300 @@ +==================== +The newforms library +==================== + +``django.newforms`` is a new replacement for ``django.forms``, the old Django +form/manipulator/validation framework. This document explains how to use this +new form library. + +Migration plan +============== + +``django.newforms`` currently is only available in the Django development version +-- i.e., it's not available in the Django 0.95 release. For the next Django +release, our plan is to do the following: + + * As of revision [4208], we've copied the current ``django.forms`` to + ``django.oldforms``. This allows you to upgrade your code *now* rather + than waiting for the backwards-incompatible change and rushing to fix + your code after the fact. Just change your import statements like this:: + + from django import forms # old + from django import oldforms as forms # new + + * At an undecided future date, we will move the current ``django.newforms`` + to ``django.forms``. This will be a backwards-incompatible change, and + anybody who is still using the old version of ``django.forms`` at that + time will need to change their import statements, as described in the + previous bullet. + + * We will remove ``django.oldforms`` in the release *after* the next Django + release -- the release that comes after the release in which we're + creating the new ``django.forms``. + +With this in mind, we recommend you use the following import statement when +using ``django.newforms``:: + + from django import newforms as forms + +This way, your code can refer to the ``forms`` module, and when +``django.newforms`` is renamed to ``django.forms``, you'll only have to change +your ``import`` statements. + +If you prefer "``import *``" syntax, you can do the following:: + + from django.newforms import * + +This will import all fields, widgets, form classes and other various utilities +into your local namespace. Some people find this convenient; others find it +too messy. The choice is yours. + +Overview +======== + +As the ``django.forms`` ("manipulators") system before it, ``django.newforms`` +is intended to handle HTML form display, validation and redisplay. It's what +you use if you want to perform server-side validation for an HTML form. + +For example, if your Web site has a contact form that visitors can use to +send you e-mail, you'd use this library to implement the display of the HTML +form fields, along with the form validation. Any time you need to use an HTML +``
``, you can use this library. + +The library deals with these concepts: + + * **Widget** -- A class that corresponds to an HTML form widget, e.g. + ```` or ``