1
0
mirror of https://github.com/django/django.git synced 2025-10-25 06:36:07 +00:00

unicode: Merged changes from trunk up to [5182].

git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5185 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick
2007-05-11 07:28:33 +00:00
parent ce4722a52a
commit a7a756e27e
53 changed files with 6926 additions and 3900 deletions

View File

@@ -396,10 +396,11 @@ To run the tests, ``cd`` to the ``tests/`` directory and type::
./runtests.py --settings=path.to.django.settings
Yes, the unit tests need a settings module, but only for database connection
info -- the ``DATABASE_ENGINE``, ``DATABASE_USER`` and ``DATABASE_PASSWORD``.
You will also need a ``ROOT_URLCONF`` setting (its value is ignored; it just
needs to be present) and a ``SITE_ID`` setting (any integer value will do) in
order for all the tests to pass.
info -- the ``DATABASE_NAME`` (required, but will be ignored),
``DATABASE_ENGINE``, ``DATABASE_USER`` and ``DATABASE_PASSWORD`` settings. You
will also need a ``ROOT_URLCONF`` setting (its value is ignored; it just needs
to be present) and a ``SITE_ID`` setting (any integer value will do) in order
for all the tests to pass.
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

View File

@@ -20,14 +20,14 @@ In two lines::
send_mail('Subject here', 'Here is the message.', 'from@example.com',
['to@example.com'], fail_silently=False)
Mail will be sent using the SMTP host and port specified in the `EMAIL_HOST`_
and `EMAIL_PORT`_ settings. The `EMAIL_HOST_USER`_ and `EMAIL_HOST_PASSWORD`_
settings, if set, will be used to authenticate to the SMTP server and the
`EMAIL_USE_TLS`_ settings will control whether a secure connection is used.
Mail is sent using the SMTP host and port specified in the `EMAIL_HOST`_ and
`EMAIL_PORT`_ settings. The `EMAIL_HOST_USER`_ and `EMAIL_HOST_PASSWORD`_
settings, if set, are used to authenticate to the SMTP server, and the
`EMAIL_USE_TLS`_ setting controls whether a secure connection is used.
.. note::
The character set of email sent with ``django.core.mail`` will be set to
The character set of e-mail sent with ``django.core.mail`` will be set to
the value of your `DEFAULT_CHARSET setting`_.
.. _DEFAULT_CHARSET setting: ../settings/#default-charset
@@ -37,7 +37,6 @@ settings, if set, will be used to authenticate to the SMTP server and the
.. _EMAIL_HOST_PASSWORD: ../settings/#email-host-password
.. _EMAIL_USE_TLS: ../settings/#email-use-tls
send_mail()
===========
@@ -193,57 +192,64 @@ The EmailMessage and SMTPConnection classes
Django's ``send_mail()`` and ``send_mass_mail()`` functions are actually thin
wrappers that make use of the ``EmailMessage`` and ``SMTPConnection`` classes
in ``django.mail``. If you ever need to customize the way Django sends email,
you can subclass these two classes to suit your needs.
in ``django.core.mail``. If you ever need to customize the way Django sends
e-mail, you can subclass these two classes to suit your needs.
.. note::
Not all features of the ``EmailMessage`` class are available through the
``send_mail()`` and related wrapper functions. If you wish to use advanced
features such as including BCC recipients or multi-part email, you will
need to create ``EmailMessage`` instances directly.
features, such as BCC'ed recipients or multi-part e-mail, you'll need to
create ``EmailMessage`` instances directly.
In general, ``EmailMessage`` is responsible for creating the email message
In general, ``EmailMessage`` is responsible for creating the e-mail message
itself. ``SMTPConnection`` is responsible for the network connection side of
the operation. This means you can reuse the same connection (an
``SMTPConnection`` instance) for multiple messages.
The ``EmailMessage`` class is initialised as follows::
The ``EmailMessage`` class is initialized as follows::
email = EmailMessage(subject, body, from_email, to, bcc, connection)
All of these parameters are optional. If ``from_email`` is omitted, the value
from ``settings.DEFAULT_FROM_EMAIL`` is used. Both the ``to`` and ``bcc``
parameters are lists of addresses.
parameters are lists of addresses, as strings.
The class has the following methods that you can use:
For example::
* ``send()`` sends the message, using either the connection that is specified
in the ``connection`` attribute, or creating a new connection if none already
exists.
* ``message()`` constructs a ``django.core.mail.SafeMIMEText`` object (a
sub-class of Python's ``email.MIMEText.MIMEText`` class) holding the
message to be sent. If you ever need to extend the `EmailMessage` class,
you will probably want to override this method to put the content you wish
into the MIME object.
* ``recipients()`` returns a lists of all the recipients of the message,
whether they are recorded in the ``to`` or ``bcc`` attributes. This is
another method you need to possibly override when sub-classing, since the
SMTP server needs to be told the full list of recipients when the message
is sent. If you add another way to specify recipients in your class, they
need to be returned from this method as well.
email = EmailMessage('Hello', 'Body goes here', 'from@example.com',
['to1@example.com', 'to2@example.com'],
['bcc@example.com'])
The class has the following methods:
* ``send()`` sends the message, using either the connection that is
specified in the ``connection`` attribute, or creating a new connection
if none already exists.
* ``message()`` constructs a ``django.core.mail.SafeMIMEText`` object (a
sub-class of Python's ``email.MIMEText.MIMEText`` class) holding the
message to be sent. If you ever need to extend the `EmailMessage` class,
you'll probably want to override this method to put the content you wish
into the MIME object.
* ``recipients()`` returns a list of all the recipients of the message,
whether they're recorded in the ``to`` or ``bcc`` attributes. This is
another method you might need to override when sub-classing, because the
SMTP server needs to be told the full list of recipients when the message
is sent. If you add another way to specify recipients in your class, they
need to be returned from this method as well.
The ``SMTPConnection`` class is initialized with the host, port, username and
password for the SMTP server. If you don't specify one or more of those
options, they are read from your settings file.
If you are sending lots of messages at once, the ``send_messages()`` method of
the ``SMTPConnection`` class will be useful. It takes a list of ``EmailMessage``
instances (or sub-classes) and sends them over a single connection. For
example, if you have a function called ``get_notification_email()`` that returns a
list of ``EmailMessage`` objects representing some periodic email you wish to
If you're sending lots of messages at once, the ``send_messages()`` method of
the ``SMTPConnection`` class is useful. It takes a list of ``EmailMessage``
instances (or subclasses) and sends them over a single connection. For example,
if you have a function called ``get_notification_email()`` that returns a
list of ``EmailMessage`` objects representing some periodic e-mail you wish to
send out, you could send this with::
connection = SMTPConnection() # Use default settings for connection
messages = get_notification_email()
connection.send_messages(messages)

View File

@@ -310,7 +310,7 @@ To create or update a message file, run this command::
...where ``de`` is the language code for the message file you want to create.
The language code, in this case, is in locale format. For example, it's
``pt_BR`` for Brazilian and ``de_AT`` for Austrian German.
``pt_BR`` for Brazilian Portugese and ``de_AT`` for Austrian German.
The script should be run from one of three places:
@@ -463,8 +463,8 @@ following this algorithm:
Notes:
* In each of these places, the language preference is expected to be in the
standard language format, as a string. For example, Brazilian is
``pt-br``.
standard language format, as a string. For example, Brazilian Portugese
is ``pt-br``.
* If a base language is available but the sublanguage specified is not,
Django uses the base language. For example, if a user specifies ``de-at``
(Austrian German) but Django only has ``de`` available, Django uses

View File

@@ -459,7 +459,7 @@ string, not ``NULL``.
``blank``
~~~~~~~~~
If ``True``, the field is allowed to be blank.
If ``True``, the field is allowed to be blank. Default is ``False``.
Note that this is different than ``null``. ``null`` is purely
database-related, whereas ``blank`` is validation-related. If a field has

View File

@@ -109,7 +109,7 @@ serializer, you must pass ``ensure_ascii=False`` as a parameter to the
For example::
json_serializer = serializers.get_serializer("json")
json_serializer = serializers.get_serializer("json")()
json_serializer.serialize(queryset, ensure_ascii=False, stream=response)
Writing custom serializers

View File

@@ -2,8 +2,6 @@
The sitemap framework
=====================
**New in Django development version**.
Django comes with a high-level sitemap-generating framework that makes
creating sitemap_ XML files easy.

View File

@@ -212,21 +212,24 @@ template tags. If an invalid variable is provided to one of these template
tags, the variable will be interpreted as ``None``. Filters are always
applied to invalid variables within these template tags.
If ``TEMPLATE_STRING_IF_INVALID`` contains a ``'%s'``, the format marker will
be replaced with the name of the invalid variable.
.. admonition:: For debug purposes only!
While ``TEMPLATE_STRING_IF_INVALID`` can be a useful debugging tool,
it is a bad idea to turn it on as a 'development default'.
While ``TEMPLATE_STRING_IF_INVALID`` can be a useful debugging tool,
it is a bad idea to turn it on as a 'development default'.
Many templates, including those in the Admin site, rely upon the
silence of the template system when a non-existent variable is
Many templates, including those in the Admin site, rely upon the
silence of the template system when a non-existent variable is
encountered. If you assign a value other than ``''`` to
``TEMPLATE_STRING_IF_INVALID``, you will experience rendering
``TEMPLATE_STRING_IF_INVALID``, you will experience rendering
problems with these templates and sites.
Generally, ``TEMPLATE_STRING_IF_INVALID`` should only be enabled
in order to debug a specific template problem, then cleared
Generally, ``TEMPLATE_STRING_IF_INVALID`` should only be enabled
in order to debug a specific template problem, then cleared
once debugging is complete.
Playing with Context objects
----------------------------
@@ -866,7 +869,7 @@ current context, available in the ``render`` method::
try:
actual_date = resolve_variable(self.date_to_be_formatted, context)
return actual_date.strftime(self.format_string)
except VariableDoesNotExist:
except template.VariableDoesNotExist:
return ''
``resolve_variable`` will try to resolve ``blog_entry.date_updated`` and then

View File

@@ -2,19 +2,29 @@
Testing Django applications
===========================
Automated testing is an extremely useful weapon in the bug-killing arsenal
of the modern developer. When initially writing code, a test suite can be
used to validate that code behaves as expected. When refactoring or
modifying code, tests serve as a guide to ensure that behavior hasn't
changed unexpectedly as a result of the refactor.
Automated testing is an extremely useful bug-killing tool for the modern
Web developer. You can use a collection of tests -- a **test suite** -- to
to solve, or avoid, a number of problems:
Testing a web application is a complex task, as there are many
components of a web application that must be validated and tested. To
help you test your application, Django provides a test execution
framework, and range of utilities that can be used to simulate and
inspect various facets of a web application.
* When you're writing new code, you can use tests to validate your code
works as expected.
This testing framework is currently under development, and may change
* When you're refactoring or modifying old code, you can use tests to
ensure your changes haven't affected your application's behavior
unexpectedly.
Testing a Web application is a complex task, because a Web application is made
of several layers of logic -- from HTTP-level request handling, to form
validation and processing, to template rendering. With Django's test-execution
framework and assorted utilities, you can simulate requests, insert test data,
inspect your application's output and generally verify your code is doing what
it should be doing.
The best part is, it's really easy.
.. admonition:: Note
This testing framework is currently under development. It may change
slightly before the next official Django release.
(That's *no* excuse not to write tests, though!)
@@ -167,6 +177,7 @@ tools that can be used to establish tests and test conditions.
* `Test Client`_
* `TestCase`_
* `Email services`_
Test Client
-----------
@@ -216,21 +227,21 @@ can be invoked on the ``Client`` instance.
``post(path, data={}, content_type=MULTIPART_CONTENT)``
Make a POST request on the provided ``path``. If you provide a content type
(e.g., ``text/xml`` for an XML payload), the contents of ``data`` will be
sent as-is in the POST request, using the content type in the HTTP
(e.g., ``text/xml`` for an XML payload), the contents of ``data`` will be
sent as-is in the POST request, using the content type in the HTTP
``Content-Type`` header.
If you do not provide a value for ``content_type``, the values in
If you do not provide a value for ``content_type``, the values in
``data`` will be transmitted with a content type of ``multipart/form-data``.
The key-value pairs in the data dictionary will be encoded as a multipart
message and used to create the POST data payload.
To submit multiple values for a given key (for example, to specify
the selections for a multiple selection list), provide the values as a
To submit multiple values for a given key (for example, to specify
the selections for a multiple selection list), provide the values as a
list or tuple for the required key. For example, a data dictionary of
``{'choices': ('a','b','d')}`` would submit three selected rows for the
field named ``choices``.
Submitting files is a special case. To POST a file, you need only
provide the file field name as a key, and a file handle to the file you wish to
upload as a value. The Test Client will populate the two POST fields (i.e.,
@@ -246,29 +257,42 @@ can be invoked on the ``Client`` instance.
file name), and `attachment_file` (containing the file data). Note that you
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 decorator provided by ``django.contrib.auth``. Interacting
with a URL that has been login protected is a slightly complex operation,
so the Test Client provides a simple method to automate the login process. A
call to ``login()`` stimulates the series of GET and POST calls required
to log a user into a @login_required protected view.
``login(**credentials)``
**New in Django development version**
If login is possible, the final return value of ``login()`` is the response
that is generated by issuing a GET request on the protected URL. If login
is not possible, ``login()`` returns False.
On a production site, it is likely that some views will be protected from
anonymous access through the use of the @login_required decorator, or some
other login checking mechanism. The ``login()`` method can be used to
simulate the effect of a user logging into the site. As a result of calling
this method, the Client will have all the cookies and session data required
to pass any login-based tests that may form part of a view.
In most cases, the ``credentials`` required by this method are the username
and password of the user that wants to log in, provided as keyword
arguments::
c = Client()
c.login(username='fred', password='secret')
# Now you can access a login protected view
If you are using a different authentication backend, this method may
require different credentials.
``login()`` returns ``True`` if it the credentials were accepted and login
was successful.
Note that since the test suite will be executed using the test database,
which contains no users by default. As a result, logins for your production
site will not work. You will need to create users as part of the test suite
to be able to test logins to your application.
which contains no users by default. As a result, logins that are valid
on your production site will not work under test conditions. You will
need to create users as part of the test suite (either manually, or
using a test fixture).
Testing Responses
~~~~~~~~~~~~~~~~~
The ``get()``, ``post()`` and ``login()`` methods all return a Response
object. This Response object has the following properties that can be used
for testing purposes:
The ``get()`` and ``post()`` methods both return a Response object. This
Response object has the following properties that can be used for testing
purposes:
=============== ==========================================================
Property Description
@@ -360,23 +384,23 @@ The following is a simple unit test using the Test Client::
TestCase
--------
Normal python unit tests extend a base class of ``unittest.testCase``.
Django provides an extension of this base class - ``django.test.TestCase``
- that provides some additional capabilities that can be useful for
testing web sites.
Normal python unit tests extend a base class of ``unittest.testCase``.
Django provides an extension of this base class - ``django.test.TestCase``
- that provides some additional capabilities that can be useful for
testing web sites.
Moving from a normal unittest TestCase to a Django TestCase is easy - just
change the base class of your test from ``unittest.TestCase`` to
change the base class of your test from ``unittest.TestCase`` to
``django.test.TestCase``. All of the standard Python unit test facilities
will continue to be available, but they will be augmented with some useful
extra facilities.
Default Test Client
~~~~~~~~~~~~~~~~~~~
** New in Django development version **
**New in Django development version**
Every test case in a ``django.test.TestCase`` instance has access to an
instance of a Django `Test Client`_. This Client can be accessed as
instance of a Django `Test Client`_. This Client can be accessed as
``self.client``. This client is recreated for each test.
Fixture loading
@@ -392,20 +416,20 @@ comprise the fixture can be distributed over multiple directories, in
multiple applications.
.. note::
If you have synchronized a Django project, you have already experienced
If you have synchronized a Django project, you have already experienced
the use of one fixture -- the ``initial_data`` fixture. Every time you
synchronize the database, Django installs the ``initial_data`` fixture.
This provides a mechanism to populate a new database with any initial
data (such as a default set of categories). Fixtures with other names
can be installed manually using ``django-admin.py loaddata``.
can be installed manually using ``django-admin.py loaddata``.
However, for the purposes of unit testing, each test must be able to
However, for the purposes of unit testing, each test must be able to
guarantee the contents of the database at the start of each and every
test.
test.
To define a fixture for a test, all you need to do is add a class
attribute to your test describing the fixtures you want the test to use.
For example, the test case from `Writing unittests`_ would
For example, the test case from `Writing unittests`_ would
look like::
from django.test import TestCase
@@ -413,41 +437,115 @@ look like::
class AnimalTestCase(TestCase):
fixtures = ['mammals.json', 'birds']
def setUp(self):
# test definitions as before
At the start of each test case, before ``setUp()`` is run, Django will
flush the database, returning the database the state it was in directly
after ``syncdb`` was called. Then, all the named fixtures are installed.
flush the database, returning the database the state it was in directly
after ``syncdb`` was called. Then, all the named fixtures are installed.
In this example, any JSON fixture called ``mammals``, and any fixture
named ``birds`` will be installed. See the documentation on
named ``birds`` will be installed. See the documentation on
`loading fixtures`_ for more details on defining and installing fixtures.
.. _`loading fixtures`: ../django-admin/#loaddata-fixture-fixture
This flush/load procedure is repeated for each test in the test case, so you
can be certain that the outcome of a test will not be affected by
This flush/load procedure is repeated for each test in the test case, so you
can be certain that the outcome of a test will not be affected by
another test, or the order of test execution.
Emptying the test outbox
~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version**
At the start of each test case, in addition to installing fixtures,
Django clears the contents of the test email outbox.
For more detail on email services during tests, see `Email services`_.
Assertions
~~~~~~~~~~
** New in Django development version **
**New in Django development version**
Normal Python unit tests have a wide range of assertions, such as
``assertTrue`` and ``assertEquals`` that can be used to validate behavior.
Normal Python unit tests have a wide range of assertions, such as
``assertTrue`` and ``assertEquals`` that can be used to validate behavior.
``django.TestCase`` adds to these, providing some assertions
that can be useful in testing the behavior of web sites.
``assertRedirects(response, expected_path)``
Assert that the response received redirects the browser to the provided
path, and that the expected_path can be retrieved.
``assertContains(response, text, count=1)``
Assert that a response indicates that a page was retreived successfully,
(i.e., the HTTP status code was 200), and that ``text`` occurs ``count``
``assertContains(response, text, count=1, status_code=200)``
Assert that a response indicates that a page could be retrieved and
produced the nominated status code, and that ``text`` occurs ``count``
times in the content of the response.
``assertFormError(response, form, field, errors)``
Assert that a field on a form raised the provided list of errors when
rendered on the form.
``form`` is the name the form object was given in the template context.
``field`` is the name of the field on the form to check. If ``field``
has a value of ``None``, non-field errors will be checked.
``errors`` is an error string, or a list of error strings, that are
expected as a result of form validation.
``assertTemplateNotUsed(response, template_name)``
Assert that the template with the given name was *not* used in rendering
the response.
``assertRedirects(response, expected_path, status_code=302, target_status_code=200)``
Assert that the response received produced the nominated status code,
redirects the browser to the provided path, and that retrieving the provided
path yields a response with the target status code.
``assertTemplateUsed(response, template_name)``
Assert that the template with the given name was used in rendering the
response.
Email services
--------------
**New in Django development version**
If your view makes use of the `Django email services`_, you don't really
want email to be sent every time you run a test using that view.
When the Django test framework is initialized, it transparently replaces the
normal `SMTPConnection`_ class with a dummy implementation that redirects all
email to a dummy outbox. This outbox, stored as ``django.core.mail.outbox``,
is a simple list of all `EmailMessage`_ instances that have been sent.
For example, during test conditions, it would be possible to run the following
code::
from django.core import mail
# Send message
mail.send_mail('Subject here', 'Here is the message.', 'from@example.com',
['to@example.com'], fail_silently=False)
# One message has been sent
self.assertEqual(len(mail.outbox), 1)
# Subject of first message is correct
self.assertEqual(mail.outbox[0].subject, 'Subject here')
The ``mail.outbox`` object does not exist under normal execution conditions.
The outbox is created during test setup, along with the dummy `SMTPConnection`_.
When the test framework is torn down, the standard `SMTPConnection`_ class
is restored, and the test outbox is destroyed.
As noted `previously`_, the test outbox is emptied at the start of every
test in a Django TestCase. To empty the outbox manually, assign the empty list
to mail.outbox::
from django.core import mail
# Empty the test outbox
mail.outbox = []
.. _`Django email services`: ../email/
.. _`SMTPConnection`: ../email/#the-emailmessage-and-smtpconnection-classes
.. _`EmailMessage`: ../email/#the-emailmessage-and-smtpconnection-classes
.. _`previously`: #emptying-the-test-outbox
Running tests
=============
@@ -472,6 +570,10 @@ database settings will the same as they would be for the project normally.
If you wish to use a name other than the default for the test database,
you can use the ``TEST_DATABASE_NAME`` setting to provide a name.
The test database is created by the user in the ``DATABASE_USER`` setting.
This user needs to have sufficient privileges to create a new database on the
system.
Once the test database has been established, Django will run your tests.
If everything goes well, at the end you'll see::
@@ -506,11 +608,11 @@ failed::
FAILED (failures=1)
The return code for the script is the total number of failed and erroneous
The return code for the script is the total number of failed and erroneous
tests. If all the tests pass, the return code is 0.
Regardless of whether the tests pass or fail, the test database is destroyed when
all the tests have been executed.
all the tests have been executed.
Using a different testing framework
===================================
@@ -521,7 +623,7 @@ it does provide a mechanism to allow you to invoke tests constructed for
an alternative framework as if they were normal Django tests.
When you run ``./manage.py test``, Django looks at the ``TEST_RUNNER``
setting to determine what to do. By default, ``TEST_RUNNER`` points to
setting to determine what to do. By default, ``TEST_RUNNER`` points to
``django.test.simple.run_tests``. This method defines the default Django
testing behavior. This behavior involves:
@@ -551,7 +653,7 @@ arguments:
Verbosity determines the amount of notification and debug information that
will be printed to the console; `0` is no output, `1` is normal output,
and `2` is verbose output.
This method should return the number of tests that failed.
Testing utilities
@@ -562,11 +664,12 @@ a number of utility methods in the ``django.test.utils`` module.
``setup_test_environment()``
Performs any global pre-test setup, such as the installing the
instrumentation of the template rendering system.
instrumentation of the template rendering system and setting up
the dummy SMTPConnection.
``teardown_test_environment()``
Performs any global post-test teardown, such as removing the instrumentation
of the template rendering system.
of the template rendering system and restoring normal email services.
``create_test_db(verbosity=1, autoclobber=False)``
Creates a new test database, and run ``syncdb`` against it.