diff options
| author | Christopher Long <indirecthit@gmail.com> | 2006-09-23 18:18:58 +0000 |
|---|---|---|
| committer | Christopher Long <indirecthit@gmail.com> | 2006-09-23 18:18:58 +0000 |
| commit | 5ea24f0c141a90f1e9a61ca7a8397cc28566623f (patch) | |
| tree | f6946d2ab0ab835408e7a30032bca807816d3572 /docs | |
| parent | 13d039ddabc79113bb319a668a8283097de4d165 (diff) | |
[per-object-permissions] Merged to trunk [3809]
git-svn-id: http://code.djangoproject.com/svn/django/branches/per-object-permissions@3810 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/authentication.txt | 40 | ||||
| -rw-r--r-- | docs/contributing.txt | 33 | ||||
| -rw-r--r-- | docs/db-api.txt | 2 | ||||
| -rw-r--r-- | docs/django-admin.txt | 6 | ||||
| -rw-r--r-- | docs/fastcgi.txt | 4 | ||||
| -rw-r--r-- | docs/forms.txt | 43 | ||||
| -rw-r--r-- | docs/model-api.txt | 4 | ||||
| -rw-r--r-- | docs/serialization.txt | 15 | ||||
| -rw-r--r-- | docs/settings.txt | 6 | ||||
| -rw-r--r-- | docs/templates_python.txt | 17 | ||||
| -rw-r--r-- | docs/testing.txt | 22 |
11 files changed, 143 insertions, 49 deletions
diff --git a/docs/authentication.txt b/docs/authentication.txt index d10dda28ef..31a894512a 100644 --- a/docs/authentication.txt +++ b/docs/authentication.txt @@ -82,14 +82,14 @@ Methods ``user_permissions``. ``User`` objects can access their related objects in the same way as any other `Django model`_:: - myuser.objects.groups = [group_list] - myuser.objects.groups.add(group, group,...) - myuser.objects.groups.remove(group, group,...) - myuser.objects.groups.clear() - myuser.objects.permissions = [permission_list] - myuser.objects.permissions.add(permission, permission, ...) - myuser.objects.permissions.remove(permission, permission, ...] - myuser.objects.permissions.clear() + myuser.groups = [group_list] + myuser.groups.add(group, group,...) + myuser.groups.remove(group, group,...) + myuser.groups.clear() + myuser.permissions = [permission_list] + myuser.permissions.add(permission, permission, ...) + myuser.permissions.remove(permission, permission, ...] + myuser.permissions.clear() In addition to those automatic API methods, ``User`` objects have the following custom methods: @@ -456,6 +456,10 @@ As a shortcut, you can use the convenient ``user_passes_test`` decorator:: # ... my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'))(my_view) +We are using this particular test as a relatively simple example, however be +aware that if you just want to test if a permission is available to a user, +you can use the ``permission_required()`` decorator described below. + Here's the same thing, using Python 2.4's decorator syntax:: from django.contrib.auth.decorators import user_passes_test @@ -488,6 +492,24 @@ Example in Python 2.4 syntax:: def my_view(request): # ... +The permission_required decorator +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since checking whether a user has a particular permission available to them is a +relatively common operation, Django provides a shortcut for that particular +case: the ``permission_required()`` decorator. Using this decorator, the +earlier example can be written as:: + + from django.contrib.auth.decorators import permission_required + + def my_view(request): + # ... + + my_view = permission_required('polls.can_vote')(my_view) + +Note that ``permission_required()`` also takes an optional ``login_url`` +parameter. + Limiting access to generic views -------------------------------- @@ -677,7 +699,7 @@ timestamps. Messages are used by the Django admin after successful actions. For example, ``"The poll Foo was created successfully."`` is a message. -The API is simple:: +The API is simple: * To create a new message, use ``user_obj.message_set.create(message='message_text')``. diff --git a/docs/contributing.txt b/docs/contributing.txt index 3d101c3241..7ecda7425c 100644 --- a/docs/contributing.txt +++ b/docs/contributing.txt @@ -247,18 +247,23 @@ Django tarball. It's our policy to make sure all tests pass at all times. The tests cover: - * Models and the database API (``tests/testapp/models``). - * The cache system (``tests/otherthests/cache.py``). - * The ``django.utils.dateformat`` module (``tests/othertests/dateformat.py``). - * Database typecasts (``tests/othertests/db_typecasts.py``). - * The template system (``tests/othertests/templates.py`` and - ``tests/othertests/defaultfilters.py``). - * ``QueryDict`` objects (``tests/othertests/httpwrappers.py``). - * Markup template tags (``tests/othertests/markup.py``). - * The ``django.utils.timesince`` module (``tests/othertests/timesince.py``). + * Models and the database API (``tests/modeltests/``). + * The cache system (``tests/regressiontests/cache.py``). + * The ``django.utils.dateformat`` module (``tests/regressiontests/dateformat/``). + * Database typecasts (``tests/regressiontests/db_typecasts/``). + * The template system (``tests/regressiontests/templates/`` and + ``tests/regressiontests/defaultfilters/``). + * ``QueryDict`` objects (``tests/regressiontests/httpwrappers/``). + * Markup template tags (``tests/regressiontests/markup/``). We appreciate any and all contributions to the test suite! +The Django tests all use the testing infrastructure that ships with Django for +testing applications. See `Testing Django Applications`_ for an explanation of +how to write new tests. + +.. _Testing Django Applications: http://www.djangoproject.com/documentation/testing/ + Running the unit tests ---------------------- @@ -268,10 +273,14 @@ To run the tests, ``cd`` to the ``tests/`` directory and type:: Yes, the unit tests need a settings module, but only for database connection info -- the ``DATABASE_ENGINE``, ``DATABASE_USER`` and ``DATABASE_PASSWORD``. +You will also need a ``ROOT_URLCONF`` setting (it's value is ignored; it just +needs to be present) and a ``SITE_ID`` setting (any integer value will do) in +order for all the tests to pass. -The unit tests will not touch your database; they create a new database, called -``django_test_db``, which is deleted when the tests are finished. This means -your user account needs permission to execute ``CREATE DATABASE``. +The unit tests will not touch your existing databases; they create a new +database, called ``django_test_db``, which is deleted when the tests are +finished. This means your user account needs permission to execute ``CREATE +DATABASE``. Requesting features =================== diff --git a/docs/db-api.txt b/docs/db-api.txt index bd178dbd7d..7800ff324a 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -1511,7 +1511,7 @@ Many-to-many relationships -------------------------- Both ends of a many-to-many relationship get automatic API access to the other -end. The API works just as a "backward" one-to-many relationship. See _Backward +end. The API works just as a "backward" one-to-many relationship. See Backward_ above. The only difference is in the attribute naming: The model that defines the diff --git a/docs/django-admin.txt b/docs/django-admin.txt index 672200c5e7..ffafc83972 100644 --- a/docs/django-admin.txt +++ b/docs/django-admin.txt @@ -295,6 +295,8 @@ give you the option of creating a superuser immediately. test ---- +**New in Django development version** + Discover and run tests for all installed models. See `Testing Django applications`_ for more information. .. _testing django applications: ../testing/ @@ -348,6 +350,8 @@ options. --noinput --------- +**New in Django development version** + Inform django-admin that the user should NOT be prompted for any input. Useful if the django-admin script will be executed as an unattended, automated script. @@ -369,6 +373,8 @@ Example output:: --verbosity ----------- +**New in Django development version** + Example usage:: django-admin.py syncdb --verbosity=2 diff --git a/docs/fastcgi.txt b/docs/fastcgi.txt index 41d50d97a1..e2f4e933b4 100644 --- a/docs/fastcgi.txt +++ b/docs/fastcgi.txt @@ -270,7 +270,7 @@ In your Web root directory, add this to a file named ``.htaccess`` :: AddHandler fastcgi-script .fcgi RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L] + RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L] Then, create a small script that tells Apache how to spawn your FastCGI program. Create a file ``mysite.fcgi`` and place it in your Web directory, and @@ -289,7 +289,7 @@ be sure to make it executable :: os.environ['DJANGO_SETTINGS_MODULE'] = "myproject.settings" from django.core.servers.fastcgi import runfastcgi - runfastcgi(["method=threaded", "daemonize=false"]) + runfastcgi(method="threaded", daemonize="false") Restarting the spawned server ----------------------------- diff --git a/docs/forms.txt b/docs/forms.txt index 67408f3c5d..0ffb0bdcb7 100644 --- a/docs/forms.txt +++ b/docs/forms.txt @@ -136,7 +136,7 @@ template:: {% endblock %} Before we get back to the problems with these naive set of views, let's go over -some salient points of the above template:: +some salient points of the above template: * Field "widgets" are handled for you: ``{{ form.field }}`` automatically creates the "right" type of widget for the form, as you can see with the @@ -148,8 +148,8 @@ some salient points of the above template:: If you must use tables, use tables. If you're a semantic purist, you can probably find better HTML than in the above template. - * To avoid name conflicts, the ``id``s of form elements take the form - "id_*fieldname*". + * To avoid name conflicts, the ``id`` values of form elements take the + form "id_*fieldname*". By creating a creation form we've solved problem number 3 above, but we still don't have any validation. Let's revise the validation issue by writing a new @@ -321,7 +321,7 @@ about editing an existing one? It's shockingly similar to creating a new one:: else: errors = {} # This makes sure the form accurate represents the fields of the place. - new_data = place.__dict__ + new_data = manipulator.flatten_data() form = forms.FormWrapper(manipulator, new_data, errors) return render_to_response('places/edit_form.html', {'form': form, 'place': place}) @@ -336,10 +336,10 @@ The only real differences are: * ``ChangeManipulator.original_object`` stores the instance of the object being edited. - * We set ``new_data`` to the original object's ``__dict__``. This makes - sure the form fields contain the current values of the object. - ``FormWrapper`` does not modify ``new_data`` in any way, and templates - cannot, so this is perfectly safe. + * We set ``new_data`` based upon ``flatten_data()`` from the manipulator. + ``flatten_data()`` takes the data from the original object under + manipulation, and converts it into a data dictionary that can be used + to populate form elements with the existing values for the object. * The above example uses a different template, so create and edit can be "skinned" differently if needed, but the form chunk itself is completely @@ -481,6 +481,33 @@ the data being validated. Also, because consistency in user interfaces is important, we strongly urge you to put punctuation at the end of your validation messages. +When Are Validators Called? +--------------------------- + +After a form has been submitted, Django first checks to see that all the +required fields are present and non-empty. For each field that passes that +test *and if the form submission contained data* for that field, all the +validators for that field are called in turn. The emphasised portion in the +last sentence is important: if a form field is not submitted (because it +contains no data -- which is normal HTML behaviour), the validators are not +run against the field. + +This feature is particularly important for models using +``models.BooleanField`` or custom manipulators using things like +``forms.CheckBoxField``. If the checkbox is not selected, it will not +contribute to the form submission. + +If you would like your validator to *always* run, regardless of whether the +field it is attached to contains any data, set the ``always_test`` attribute +on the validator function. For example:: + + def my_custom_validator(field_data, all_data): + # ... + + my_custom_validator.always_test = True + +This validator will always be executed for any field it is attached to. + Ready-made Validators --------------------- diff --git a/docs/model-api.txt b/docs/model-api.txt index b46a11c463..c6c4200239 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -543,7 +543,9 @@ The default value for the field. ``editable`` ~~~~~~~~~~~~ -If ``False``, the field will not be editable in the admin. Default is ``True``. +If ``False``, the field will not be editable in the admin or via form +processing using the object's ``AddManipulator`` or ``ChangeManipulator`` +classes. Default is ``True``. ``help_text`` ~~~~~~~~~~~~~ diff --git a/docs/serialization.txt b/docs/serialization.txt index 25199e7a50..694e2d25db 100644 --- a/docs/serialization.txt +++ b/docs/serialization.txt @@ -96,6 +96,21 @@ Django "ships" with a few included serializers: .. _json: http://json.org/ .. _simplejson: http://undefined.org/python/#simplejson +Notes For Specific Serialization Formats +---------------------------------------- + +json +~~~~ + +If you are using UTF-8 (or any other non-ASCII encoding) data with the JSON +serializer, you must pass ``ensure_ascii=False`` as a parameter to the +``serialize()`` call. Otherwise the output will not be encoded correctly. + +For example:: + + json_serializer = serializers.get_serializer("json") + json_serializer.serialize(queryset, ensure_ascii=False, stream=response) + Writing custom serializers `````````````````````````` diff --git a/docs/settings.txt b/docs/settings.txt index b927b62ca7..65113b3c30 100644 --- a/docs/settings.txt +++ b/docs/settings.txt @@ -596,6 +596,12 @@ Whether to prepend the "www." subdomain to URLs that don't have it. This is only used if ``CommonMiddleware`` is installed (see the `middleware docs`_). See also ``APPEND_SLASH``. +PROFANITIES_LIST +---------------- + +A list of profanities that will trigger a validation error when the +``hasNoProfanities`` validator is called. + ROOT_URLCONF ------------ diff --git a/docs/templates_python.txt b/docs/templates_python.txt index 950b122339..bc05d769ad 100644 --- a/docs/templates_python.txt +++ b/docs/templates_python.txt @@ -763,17 +763,17 @@ will use the function's name as the tag name. Shortcut for simple tags ~~~~~~~~~~~~~~~~~~~~~~~~ -Many template tags take a single argument -- a string or a template variable -reference -- and return a string after doing some processing based solely on +Many template tags take a number of arguments -- strings or a template variables +-- and return a string after doing some processing based solely on the input argument and some external information. For example, the ``current_time`` tag we wrote above is of this variety: we give it a format string, it returns the time as a string. To ease the creation of the types of tags, Django provides a helper function, ``simple_tag``. This function, which is a method of -``django.template.Library``, takes a function that accepts one argument, wraps -it in a ``render`` function and the other necessary bits mentioned above and -registers it with the template system. +``django.template.Library``, takes a function that accepts any number of +arguments, wraps it in a ``render`` function and the other necessary bits +mentioned above and registers it with the template system. Our earlier ``current_time`` function could thus be written like this:: @@ -789,11 +789,16 @@ In Python 2.4, the decorator syntax also works:: ... A couple of things to note about the ``simple_tag`` helper function: - * Only the (single) argument is passed into our function. * Checking for the required number of arguments, etc, has already been done by the time our function is called, so we don't need to do that. * The quotes around the argument (if any) have already been stripped away, so we just receive a plain string. + * If the argument was a template variable, our function is passed the + current value of the variable, not the variable itself. + +When your template tag does not need access to the current context, writing a +function to work with the input values and using the ``simple_tag`` helper is +the easiest way to create a new tag. Inclusion tags ~~~~~~~~~~~~~~ diff --git a/docs/testing.txt b/docs/testing.txt index f8158a0001..b1ede3e4cc 100644 --- a/docs/testing.txt +++ b/docs/testing.txt @@ -92,7 +92,8 @@ Writing unittests Like doctests, Django's unit tests use a standard library module: unittest_. As with doctests, Django's test runner looks for any unit test cases defined -in ``models.py``, or in a ``tests.py`` file in your application directory. +in ``models.py``, or in a ``tests.py`` file stored in the application +directory. An equivalent unittest test case for the above example would look like:: @@ -110,8 +111,9 @@ An equivalent unittest test case for the above example would look like:: self.assertEquals(self.cat.speak(), 'The cat says "meow"') When you `run your tests`_, the test utility will find all the test cases -(that is, subclasses of ``unittest.TestCase``) in ``tests.py``, automatically -build a test suite out of those test cases, and run that suite. +(that is, subclasses of ``unittest.TestCase``) in ``models.py`` and +``tests.py``, automatically build a test suite out of those test cases, +and run that suite. For more details about ``unittest``, see the `standard library unittest documentation`_. @@ -197,10 +199,10 @@ used as test conditions. .. _Selenium: http://www.openqa.org/selenium/ The Test Client is stateful; if a cookie is returned as part of a response, -that cookie is provided as part of the next request. Expiry policies for these -cookies are not followed; if you want a cookie to expire, either delete it -manually from ``client.cookies``, or create a new Client instance (which will -effectively delete all cookies). +that cookie is provided as part of the next request issued to that Client +instance. Expiry policies for these cookies are not followed; if you want +a cookie to expire, either delete it manually from ``client.cookies``, or +create a new Client instance (which will effectively delete all cookies). Making requests ~~~~~~~~~~~~~~~ @@ -210,7 +212,6 @@ no arguments at time of construction. Once constructed, the following methods can be invoked on the ``Client`` instance. ``get(path, data={})`` - Make a GET request on the provided ``path``. The key-value pairs in the data dictionary will be used to create a GET data payload. For example:: @@ -222,7 +223,6 @@ can be invoked on the ``Client`` instance. http://yoursite.com/customers/details/?name='fred'&age=7 ``post(path, data={})`` - Make a POST request on the provided ``path``. The key-value pairs in the data dictionary will be used to create the POST data payload. This payload will be transmitted with the mimetype ``multipart/form-data``. @@ -243,7 +243,6 @@ can be invoked on the ``Client`` instance. need to manually close the file after it has been provided to the POST. ``login(path, username, password)`` - In a production site, it is likely that some views will be protected with the @login_required URL provided by ``django.contrib.auth``. Interacting with a URL that has been login protected is a slightly complex operation, @@ -307,9 +306,12 @@ The following is a simple unit test using the Test Client:: # Every test needs a client self.client = Client() def test_details(self): + # Issue a GET request response = self.client.get('/customer/details/') + # Check that the respose is 200 OK self.failUnlessEqual(response.status_code, 200) + # Check that the rendered context contains 5 customers self.failUnlessEqual(len(response.context['customers']), 5) Fixtures |
