diff options
| author | Chris Cahoon <chris.cahoon@gmail.com> | 2009-06-25 15:42:51 +0000 |
|---|---|---|
| committer | Chris Cahoon <chris.cahoon@gmail.com> | 2009-06-25 15:42:51 +0000 |
| commit | eac54911f5df8a31377fecd37b2bf34f0afef169 (patch) | |
| tree | e5028a9673b5cbc337f380a6c808816236932f7b /docs/topics | |
| parent | 7acae8f4d8a8f191d46fbb16e8cb15f46644b2ca (diff) | |
[soc2009/http-wsgi-improvements] Merged up to 11103 from trunk.
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/http-wsgi-improvements@11109 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs/topics')
| -rw-r--r-- | docs/topics/db/queries.txt | 8 | ||||
| -rw-r--r-- | docs/topics/db/sql.txt | 46 | ||||
| -rw-r--r-- | docs/topics/forms/modelforms.txt | 22 | ||||
| -rw-r--r-- | docs/topics/generic-views.txt | 503 | ||||
| -rw-r--r-- | docs/topics/http/middleware.txt | 15 | ||||
| -rw-r--r-- | docs/topics/http/sessions.txt | 3 | ||||
| -rw-r--r-- | docs/topics/i18n.txt | 18 | ||||
| -rw-r--r-- | docs/topics/index.txt | 2 | ||||
| -rw-r--r-- | docs/topics/install.txt | 35 | ||||
| -rw-r--r-- | docs/topics/testing.txt | 12 |
10 files changed, 628 insertions, 36 deletions
diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt index 4aa54261c4..5e353b2ec3 100644 --- a/docs/topics/db/queries.txt +++ b/docs/topics/db/queries.txt @@ -278,7 +278,7 @@ 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. Generally, slicing a ``QuerySet`` returns a new ``QuerySet`` -- it doesn't @@ -945,11 +945,15 @@ in the :ref:`related objects reference <ref-models-relations>`. Removes all objects from the related object set. To assign the members of a related set in one fell swoop, just assign to it -from any iterable object. Example:: +from any iterable object. The iterable can contain object instances, or just +a list of primary key values. For example:: b = Blog.objects.get(id=1) b.entry_set = [e1, e2] +In this example, ``e1`` and ``e2`` can be full Entry instances, or integer +primary key values. + If the ``clear()`` method is available, any pre-existing objects will be removed from the ``entry_set`` before all objects in the iterable (in this case, a list) are added to the set. If the ``clear()`` method is *not* diff --git a/docs/topics/db/sql.txt b/docs/topics/db/sql.txt index 4352908909..9c534709ca 100644 --- a/docs/topics/db/sql.txt +++ b/docs/topics/db/sql.txt @@ -29,6 +29,45 @@ is required. For example:: return row +.. _transactions-and-raw-sql: + +Transactions and raw SQL +------------------------ +If you are using transaction decorators (such as ``commit_on_success``) to +wrap your views and provide transaction control, you don't have to make a +manual call to ``transaction.commit_unless_managed()`` -- you can manually +commit if you want to, but you aren't required to, since the decorator will +commit for you. However, if you don't manually commit your changes, you will +need to manually mark the transaction as dirty, using +``transaction.set_dirty()``:: + + @commit_on_success + def my_custom_sql_view(request, value): + from django.db import connection, transaction + cursor = connection.cursor() + + # Data modifying operation + cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [value]) + + # Since we modified data, mark the transaction as dirty + transaction.set_dirty() + + # Data retrieval operation. This doesn't dirty the transaction, + # so no call to set_dirty() is required. + cursor.execute("SELECT foo FROM bar WHERE baz = %s", [value]) + row = cursor.fetchone() + + return render_to_response('template.html', {'row': row}) + +The call to ``set_dirty()`` is made automatically when you use the Django ORM +to make data modifying database calls. However, when you use raw SQL, Django +has no way of knowing if your SQL modifies data or not. The manual call to +``set_dirty()`` ensures that Django knows that there are modifications that +must be committed. + +Connections and cursors +----------------------- + ``connection`` and ``cursor`` mostly implement the standard `Python DB-API`_ (except when it comes to :ref:`transaction handling <topics-db-transactions>`). If you're not familiar with the Python DB-API, note that the SQL statement in @@ -39,9 +78,12 @@ necessary. (Also note that Django expects the ``"%s"`` placeholder, *not* the ``"?"`` placeholder, which is used by the SQLite Python bindings. This is for the sake of consistency and sanity.) +An easier option? +----------------- + A final note: If all you want to do is a custom ``WHERE`` clause, you can just -use the ``where``, ``tables`` and ``params`` arguments to the standard lookup -API. +use the ``where``, ``tables`` and ``params`` arguments to the +:ref:`extra clause <extra>` in the standard queryset API. .. _Python DB-API: http://www.python.org/peps/pep-0249.html diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt index 690ca7f391..add581268b 100644 --- a/docs/topics/forms/modelforms.txt +++ b/docs/topics/forms/modelforms.txt @@ -397,16 +397,26 @@ to be rendered first, we could specify the following ``ModelForm``:: ... model = Book ... fields = ['title', 'author'] +.. _overriding-modelform-clean-method: Overriding the clean() method ----------------------------- You can override the ``clean()`` method on a model form to provide additional -validation in the same way you can on a normal form. However, by default the -``clean()`` method validates the uniqueness of fields that are marked as -``unique``, ``unique_together`` or ``unique_for_date|month|year`` on the model. -Therefore, if you would like to override the ``clean()`` method and maintain the -default validation, you must call the parent class's ``clean()`` method. +validation in the same way you can on a normal form. + +In this regard, model forms have two specific characteristics when compared to +forms: + +By default the ``clean()`` method validates the uniqueness of fields that are +marked as ``unique``, ``unique_together`` or ``unique_for_date|month|year`` on +the model. Therefore, if you would like to override the ``clean()`` method and +maintain the default validation, you must call the parent class's ``clean()`` +method. + +Also, a model form instance bound to a model object will contain a +``self.instance`` attribute that gives model form methods access to that +specific model instance. Form inheritance ---------------- @@ -611,7 +621,7 @@ Just like with ``ModelForms``, by default the ``clean()`` method of a the unique constraints on your model (either ``unique``, ``unique_together`` or ``unique_for_date|month|year``). If you want to overide the ``clean()`` method on a ``model_formset`` and maintain this validation, you must call the parent -classes ``clean`` method:: +class's ``clean`` method:: class MyModelFormSet(BaseModelFormSet): def clean(self): diff --git a/docs/topics/generic-views.txt b/docs/topics/generic-views.txt new file mode 100644 index 0000000000..c7d751a86b --- /dev/null +++ b/docs/topics/generic-views.txt @@ -0,0 +1,503 @@ +.. _topics-generic-views: + +============= +Generic views +============= + +Writing Web applications can be monotonous, because we repeat certain patterns +again and again. Django tries to take away some of that monotony at the model +and template layers, but Web developers also experience this boredom at the view +level. + +Django's *generic views* were developed to ease that pain. They take certain +common idioms and patterns found in view development and abstract them so that +you can quickly write common views of data without having to write too much +code. + +We can recognize certain common tasks, like displaying a list of objects, and +write code that displays a list of *any* object. Then the model in question can +be passed as an extra argument to the URLconf. + +Django ships with generic views to do the following: + + * Perform common "simple" tasks: redirect to a different page and + render a given template. + + * Display list and detail pages for a single object. If we were creating an + application to manage conferences then a ``talk_list`` view and a + ``registered_user_list`` view would be examples of list views. A single + talk page is an example of what we call a "detail" view. + + * Present date-based objects in year/month/day archive pages, + associated detail, and "latest" pages. The Django Weblog's + (http://www.djangoproject.com/weblog/) year, month, and + day archives are built with these, as would be a typical + newspaper's archives. + + * Allow users to create, update, and delete objects -- with or + without authorization. + +Taken together, these views provide easy interfaces to perform the most common +tasks developers encounter. + +Using generic views +=================== + +All of these views are used by creating configuration dictionaries in +your URLconf files and passing those dictionaries as the third member of the +URLconf tuple for a given pattern. + +For example, here's a simple URLconf you could use to present a static "about" +page:: + + from django.conf.urls.defaults import * + from django.views.generic.simple import direct_to_template + + urlpatterns = patterns('', + ('^about/$', direct_to_template, { + 'template': 'about.html' + }) + ) + +Though this might seem a bit "magical" at first glance -- look, a view with no +code! --, actually the ``direct_to_template`` view simply grabs information from +the extra-parameters dictionary and uses that information when rendering the +view. + +Because this generic view -- and all the others -- is a regular view functions +like any other, we can reuse it inside our own views. As an example, let's +extend our "about" example to map URLs of the form ``/about/<whatever>/`` to +statically rendered ``about/<whatever>.html``. We'll do this by first modifying +the URLconf to point to a view function: + +.. parsed-literal:: + + from django.conf.urls.defaults import * + from django.views.generic.simple import direct_to_template + **from mysite.books.views import about_pages** + + urlpatterns = patterns('', + ('^about/$', direct_to_template, { + 'template': 'about.html' + }), + **('^about/(\w+)/$', about_pages),** + ) + +Next, we'll write the ``about_pages`` view:: + + from django.http import Http404 + from django.template import TemplateDoesNotExist + from django.views.generic.simple import direct_to_template + + def about_pages(request, page): + try: + return direct_to_template(request, template="about/%s.html" % page) + except TemplateDoesNotExist: + raise Http404() + +Here we're treating ``direct_to_template`` like any other function. Since it +returns an ``HttpResponse``, we can simply return it as-is. The only slightly +tricky business here is dealing with missing templates. We don't want a +nonexistent template to cause a server error, so we catch +``TemplateDoesNotExist`` exceptions and return 404 errors instead. + +.. admonition:: Is there a security vulnerability here? + + Sharp-eyed readers may have noticed a possible security hole: we're + constructing the template name using interpolated content from the browser + (``template="about/%s.html" % page``). At first glance, this looks like a + classic *directory traversal* vulnerability. But is it really? + + Not exactly. Yes, a maliciously crafted value of ``page`` could cause + directory traversal, but although ``page`` *is* taken from the request URL, + not every value will be accepted. The key is in the URLconf: we're using + the regular expression ``\w+`` to match the ``page`` part of the URL, and + ``\w`` only accepts letters and numbers. Thus, any malicious characters + (dots and slashes, here) will be rejected by the URL resolver before they + reach the view itself. + +Generic views of objects +======================== + +The ``direct_to_template`` certainly is useful, but Django's generic views +really shine when it comes to presenting views on your database content. Because +it's such a common task, Django comes with a handful of built-in generic views +that make generating list and detail views of objects incredibly easy. + +Let's take a look at one of these generic views: the "object list" view. We'll +be using these models:: + + # models.py + from django.db import models + + class Publisher(models.Model): + name = models.CharField(max_length=30) + address = models.CharField(max_length=50) + city = models.CharField(max_length=60) + state_province = models.CharField(max_length=30) + country = models.CharField(max_length=50) + website = models.URLField() + + def __unicode__(self): + return self.name + + class Meta: + ordering = ["-name"] + + class Book(models.Model): + title = models.CharField(max_length=100) + authors = models.ManyToManyField('Author') + publisher = models.ForeignKey(Publisher) + publication_date = models.DateField() + +To build a list page of all books, we'd use a URLconf along these lines:: + + from django.conf.urls.defaults import * + from django.views.generic import list_detail + from mysite.books.models import Publisher + + publisher_info = { + "queryset" : Publisher.objects.all(), + } + + urlpatterns = patterns('', + (r'^publishers/$', list_detail.object_list, publisher_info) + ) + +That's all the Python code we need to write. We still need to write a template, +however. We could explicitly tell the ``object_list`` view which template to use +by including a ``template_name`` key in the extra arguments dictionary, but in +the absence of an explicit template Django will infer one from the object's +name. In this case, the inferred template will be +``"books/publisher_list.html"`` -- the "books" part comes from the name of the +app that defines the model, while the "publisher" bit is just the lowercased +version of the model's name. + +.. highlightlang:: html+django + +This template will be rendered against a context containing a variable called +``object_list`` that contains all the book objects. A very simple template +might look like the following:: + + {% extends "base.html" %} + + {% block content %} + <h2>Publishers</h2> + <ul> + {% for publisher in object_list %} + <li>{{ publisher.name }}</li> + {% endfor %} + </ul> + {% endblock %} + +That's really all there is to it. All the cool features of generic views come +from changing the "info" dictionary passed to the generic view. The +:ref:`generic views reference<ref-generic-views>` documents all the generic +views and all their options in detail; the rest of this document will consider +some of the common ways you might customize and extend generic views. + +Extending generic views +======================= + +.. highlightlang:: python + +There's no question that using generic views can speed up development +substantially. In most projects, however, there comes a moment when the +generic views no longer suffice. Indeed, the most common question asked by new +Django developers is how to make generic views handle a wider array of +situations. + +Luckily, in nearly every one of these cases, there are ways to simply extend +generic views to handle a larger array of use cases. These situations usually +fall into a handful of patterns dealt with in the sections that follow. + +Making "friendly" template contexts +----------------------------------- + +You might have noticed that our sample publisher list template stores all the +books in a variable named ``object_list``. While this works just fine, it isn't +all that "friendly" to template authors: they have to "just know" that they're +dealing with books here. A better name for that variable would be +``publisher_list``; that variable's content is pretty obvious. + +We can change the name of that variable easily with the ``template_object_name`` +argument: + +.. parsed-literal:: + + publisher_info = { + "queryset" : Publisher.objects.all(), + **"template_object_name" : "publisher",** + } + + urlpatterns = patterns('', + (r'^publishers/$', list_detail.object_list, publisher_info) + ) + +Providing a useful ``template_object_name`` is always a good idea. Your +coworkers who design templates will thank you. + +Adding extra context +-------------------- + +Often you simply need to present some extra information beyond that provided by +the generic view. For example, think of showing a list of all the other +publishers on each publisher detail page. The ``object_detail`` generic view +provides the publisher to the context, but it seems there's no way to get a list +of *all* publishers in that template. + +But there is: all generic views take an extra optional parameter, +``extra_context``. This is a dictionary of extra objects that will be added to +the template's context. So, to provide the list of all publishers on the detail +detail view, we'd use an info dict like this: + +.. parsed-literal:: + + from mysite.books.models import Publisher, **Book** + + publisher_info = { + "queryset" : Publisher.objects.all(), + "template_object_name" : "publisher", + **"extra_context" : {"book_list" : Book.objects.all()}** + } + +This would populate a ``{{ book_list }}`` variable in the template context. +This pattern can be used to pass any information down into the template for the +generic view. It's very handy. + +However, there's actually a subtle bug here -- can you spot it? + +The problem has to do with when the queries in ``extra_context`` are evaluated. +Because this example puts ``Publisher.objects.all()`` in the URLconf, it will +be evaluated only once (when the URLconf is first loaded). Once you add or +remove publishers, you'll notice that the generic view doesn't reflect those +changes until you reload the Web server (see :ref:`caching-and-querysets` +for more information about when QuerySets are cached and evaluated). + +.. note:: + + This problem doesn't apply to the ``queryset`` generic view argument. Since + Django knows that particular QuerySet should *never* be cached, the generic + view takes care of clearing the cache when each view is rendered. + +The solution is to use a callback in ``extra_context`` instead of a value. Any +callable (i.e., a function) that's passed to ``extra_context`` will be evaluated +when the view is rendered (instead of only once). You could do this with an +explicitly defined function: + +.. parsed-literal:: + + def get_books(): + return Book.objects.all() + + publisher_info = { + "queryset" : Publisher.objects.all(), + "template_object_name" : "publisher", + "extra_context" : **{"book_list" : get_books}** + } + +or you could use a less obvious but shorter version that relies on the fact that +``Book.objects.all`` is itself a callable: + +.. parsed-literal:: + + publisher_info = { + "queryset" : Publisher.objects.all(), + "template_object_name" : "publisher", + "extra_context" : **{"book_list" : Book.objects.all}** + } + +Notice the lack of parentheses after ``Book.objects.all``; this references +the function without actually calling it (which the generic view will do later). + +Viewing subsets of objects +-------------------------- + +Now let's take a closer look at this ``queryset`` key we've been using all +along. Most generic views take one of these ``queryset`` arguments -- it's how +the view knows which set of objects to display (see :ref:`topics-db-queries` for +more information about ``QuerySet`` objects, and see the +:ref:`generic views reference<ref-generic-views>` for the complete details). + +To pick a simple example, we might want to order a list of books by +publication date, with the most recent first: + +.. parsed-literal:: + + book_info = { + "queryset" : Book.objects.all().order_by("-publication_date"), + } + + urlpatterns = patterns('', + (r'^publishers/$', list_detail.object_list, publisher_info), + **(r'^books/$', list_detail.object_list, book_info),** + ) + + +That's a pretty simple example, but it illustrates the idea nicely. Of course, +you'll usually want to do more than just reorder objects. If you want to +present a list of books by a particular publisher, you can use the same +technique: + +.. parsed-literal:: + + **acme_books = {** + **"queryset": Book.objects.filter(publisher__name="Acme Publishing"),** + **"template_name" : "books/acme_list.html"** + **}** + + urlpatterns = patterns('', + (r'^publishers/$', list_detail.object_list, publisher_info), + **(r'^books/acme/$', list_detail.object_list, acme_books),** + ) + +Notice that along with a filtered ``queryset``, we're also using a custom +template name. If we didn't, the generic view would use the same template as the +"vanilla" object list, which might not be what we want. + +Also notice that this isn't a very elegant way of doing publisher-specific +books. If we want to add another publisher page, we'd need another handful of +lines in the URLconf, and more than a few publishers would get unreasonable. +We'll deal with this problem in the next section. + +.. note:: + + If you get a 404 when requesting ``/books/acme/``, check to ensure you + actually have a Publisher with the name 'ACME Publishing'. Generic + views have an ``allow_empty`` parameter for this case. See the + :ref:`generic views reference<ref-generic-views>` for more details. + +Complex filtering with wrapper functions +---------------------------------------- + +Another common need is to filter down the objects given in a list page by some +key in the URL. Earlier we hard-coded the publisher's name in the URLconf, but +what if we wanted to write a view that displayed all the books by some arbitrary +publisher? We can "wrap" the ``object_list`` generic view to avoid writing a lot +of code by hand. As usual, we'll start by writing a URLconf: + +.. parsed-literal:: + + from mysite.books.views import books_by_publisher + + urlpatterns = patterns('', + (r'^publishers/$', list_detail.object_list, publisher_info), + **(r'^books/(\w+)/$', books_by_publisher),** + ) + +Next, we'll write the ``books_by_publisher`` view itself:: + + from django.http import Http404 + from django.views.generic import list_detail + from mysite.books.models import Book, Publisher + + def books_by_publisher(request, name): + + # Look up the publisher (and raise a 404 if it can't be found). + try: + publisher = Publisher.objects.get(name__iexact=name) + except Publisher.DoesNotExist: + raise Http404 + + # Use the object_list view for the heavy lifting. + return list_detail.object_list( + request, + queryset = Book.objects.filter(publisher=publisher), + template_name = "books/books_by_publisher.html", + template_object_name = "books", + extra_context = {"publisher" : publisher} + ) + +This works because there's really nothing special about generic views -- they're +just Python functions. Like any view function, generic views expect a certain +set of arguments and return ``HttpResponse`` objects. Thus, it's incredibly easy +to wrap a small function around a generic view that does additional work before +(or after; see the next section) handing things off to the generic view. + +.. note:: + + Notice that in the preceding example we passed the current publisher being + displayed in the ``extra_context``. This is usually a good idea in wrappers + of this nature; it lets the template know which "parent" object is currently + being browsed. + +Performing extra work +--------------------- + +The last common pattern we'll look at involves doing some extra work before +or after calling the generic view. + +Imagine we had a ``last_accessed`` field on our ``Author`` object that we were +using to keep track of the last time anybody looked at that author:: + + # models.py + + class Author(models.Model): + salutation = models.CharField(max_length=10) + first_name = models.CharField(max_length=30) + last_name = models.CharField(max_length=40) + email = models.EmailField() + headshot = models.ImageField(upload_to='/tmp') + last_accessed = models.DateTimeField() + +The generic ``object_detail`` view, of course, wouldn't know anything about this +field, but once again we could easily write a custom view to keep that field +updated. + +First, we'd need to add an author detail bit in the URLconf to point to a +custom view: + +.. parsed-literal:: + + from mysite.books.views import author_detail + + urlpatterns = patterns('', + #... + **(r'^authors/(?P<author_id>\d+)/$', author_detail),** + ) + +Then we'd write our wrapper function:: + + import datetime + from mysite.books.models import Author + from django.views.generic import list_detail + from django.shortcuts import get_object_or_404 + + def author_detail(request, author_id): + # Look up the Author (and raise a 404 if she's not found) + author = get_object_or_404(Author, pk=author_id) + + # Record the last accessed date + author.last_accessed = datetime.datetime.now() + author.save() + + # Show the detail page + return list_detail.object_detail( + request, + queryset = Author.objects.all(), + object_id = author_id, + ) + +.. note:: + + This code won't actually work unless you create a + ``books/author_detail.html`` template. + +We can use a similar idiom to alter the response returned by the generic view. +If we wanted to provide a downloadable plain-text version of the list of +authors, we could use a view like this:: + + def author_list_plaintext(request): + response = list_detail.object_list( + request, + queryset = Author.objects.all(), + mimetype = "text/plain", + template_name = "books/author_list.txt" + ) + response["Content-Disposition"] = "attachment; filename=authors.txt" + return response + +This works because the generic views return simple ``HttpResponse`` objects +that can be treated like dictionaries to set HTTP headers. This +``Content-Disposition`` business, by the way, instructs the browser to +download and save the page instead of displaying it in the browser. diff --git a/docs/topics/http/middleware.txt b/docs/topics/http/middleware.txt index 9040533f33..19facb8371 100644 --- a/docs/topics/http/middleware.txt +++ b/docs/topics/http/middleware.txt @@ -107,15 +107,18 @@ middleware is always called on every response. ``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is the :class:`~django.http. HttpResponse` object returned by a Django view. -``process_response()`` should return an :class:`~django.http. HttpResponse` +``process_response()`` must return an :class:`~django.http. HttpResponse` 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. +Unlike the ``process_request()`` and ``process_view()`` methods, the +``process_response()`` method is always called, even if the ``process_request()`` +and ``process_view()`` methods of the same middleware class were skipped because +an earlier middleware method returned an :class:`~django.http. HttpResponse` +(this means that your ``process_response()`` method cannot rely on setup done in +``process_request()``, for example). In addition, 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: diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt index fa3864a7c2..d3956504c7 100644 --- a/docs/topics/http/sessions.txt +++ b/docs/topics/http/sessions.txt @@ -4,6 +4,9 @@ How to use sessions =================== +.. module:: django.contrib.sessions + :synopsis: Provides session management for Django projects. + Django provides full support for anonymous sessions. The session framework lets you store and retrieve arbitrary data on a per-site-visitor basis. It stores data on the server side and abstracts the sending and receiving of cookies. diff --git a/docs/topics/i18n.txt b/docs/topics/i18n.txt index 140adce74c..86c03221aa 100644 --- a/docs/topics/i18n.txt +++ b/docs/topics/i18n.txt @@ -978,15 +978,17 @@ message files (``.po``). Translation work itself just involves editing existing files of this type, but if you want to create your own message files, or want to test or compile a changed message file, you will need the ``gettext`` utilities: - * Download the following zip files from - http://sourceforge.net/projects/gettext + * Download the following zip files from the GNOME servers + http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one + of its mirrors_ - * ``gettext-runtime-X.bin.woe32.zip`` - * ``gettext-tools-X.bin.woe32.zip`` - * ``libiconv-X.bin.woe32.zip`` + * ``gettext-runtime-X.zip`` + * ``gettext-tools-X.zip`` - * Extract the 3 files in the same folder (i.e. ``C:\Program - Files\gettext-utils``) + ``X`` is the version number, we recomend using ``0.15`` or higher. + + * Extract the contents of the ``bin\`` directories in both files to the + same folder on your system (i.e. ``C:\Program Files\gettext-utils``) * Update the system PATH: @@ -995,6 +997,8 @@ test or compile a changed message file, you will need the ``gettext`` utilities: * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the ``Variable value`` field +.. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS + You may also use ``gettext`` binaries you have obtained elsewhere, so long as the ``xgettext --version`` command works properly. Some version 0.14.4 binaries have been found to not support this command. Do not attempt to use Django diff --git a/docs/topics/index.txt b/docs/topics/index.txt index 20d7aa3061..7fa283aa1a 100644 --- a/docs/topics/index.txt +++ b/docs/topics/index.txt @@ -14,6 +14,7 @@ Introductions to all the key parts of Django you'll need to know: forms/index forms/modelforms templates + generic-views files testing auth @@ -25,3 +26,4 @@ Introductions to all the key parts of Django you'll need to know: serialization settings signals + diff --git a/docs/topics/install.txt b/docs/topics/install.txt index 4268759828..b66c8aef15 100644 --- a/docs/topics/install.txt +++ b/docs/topics/install.txt @@ -61,13 +61,27 @@ for each platform. Get your database running ========================= -If you plan to use Django's database API functionality, you'll need to -make sure a database server is running. Django works with PostgreSQL_, -MySQL_, Oracle_ and SQLite_ (although SQLite doesn't require a separate server -to be running). +If you plan to use Django's database API functionality, you'll need to make +sure a database server is running. Django supports many different database +servers and is officially supported with PostgreSQL_, MySQL_, Oracle_ and +SQLite_ (although SQLite doesn't require a separate server to be running). -Additionally, you'll need to make sure your Python database bindings are -installed. +In addition to the officially supported databases, there are backends provided +by 3rd parties that allow you to use other databases with Django: + +* `Sybase SQL Anywhere`_ +* `IBM DB2`_ +* `Microsoft SQL Server 2005`_ +* Firebird_ +* ODBC_ + +The Django versions and ORM features supported by these unofficial backends +vary considerably. Queries regarding the specific capabilities of these +unofficial backends, along with any support queries, should be directed to the +support channels provided by each 3rd party project. + +In addition to a database backend, you'll need to make sure your Python +database bindings are installed. * If you're using PostgreSQL, you'll need the psycopg_ package. Django supports both version 1 and 2. (When you configure Django's database layer, specify @@ -89,6 +103,9 @@ installed. :ref:`Oracle backend <oracle-notes>` for important information regarding supported versions of both Oracle and ``cx_Oracle``. +* If you're using an unofficial 3rd party backend, please consult the + documentation provided for any additional requirements. + If you plan to use Django's ``manage.py syncdb`` command to automatically create database tables for your models, you'll need to ensure that Django has permission to create and alter tables in the @@ -111,7 +128,11 @@ Django will need permission to create a test database. .. _pysqlite: http://pysqlite.org/ .. _cx_Oracle: http://cx-oracle.sourceforge.net/ .. _Oracle: http://www.oracle.com/ - +.. _Sybase SQL Anywhere: http://code.google.com/p/sqlany-django/ +.. _IBM DB2: http://code.google.com/p/ibm-db/ +.. _Microsoft SQL Server 2005: http://code.google.com/p/django-mssql/ +.. _Firebird: http://code.google.com/p/django-firebird/ +.. _ODBC: http://code.google.com/p/django-pyodbc/ .. _removing-old-versions-of-django: Remove any old versions of Django diff --git a/docs/topics/testing.txt b/docs/topics/testing.txt index 0410049297..1256a61187 100644 --- a/docs/topics/testing.txt +++ b/docs/topics/testing.txt @@ -139,8 +139,8 @@ In the case of model tests, note that the test runner takes care of creating its own test database. That is, any test that accesses a database -- by creating and saving model instances, for example -- will not affect your production database. However, the database is not refreshed between doctests, -so if your doctest requires a certain state you should consider flushin the -database or loading a fixture. (See the section on fixtures, below, for more +so if your doctest requires a certain state you should consider flushing the +database or loading a fixture. (See the section on fixtures, below, for more on this.) Note that to use this feature, the database user Django is connecting as must have ``CREATE DATABASE`` rights. @@ -1042,7 +1042,7 @@ applications: Asserts that a ``Response`` instance produced the given ``status_code`` and that ``text`` does not appears in the content of the response. -.. method:: assertFormError(response, form, field, errors) +.. method:: TestCase.assertFormError(response, form, field, errors) Asserts that a field on a form raises the provided list of errors when rendered on the form. @@ -1057,19 +1057,19 @@ applications: ``errors`` is an error string, or a list of error strings, that are expected as a result of form validation. -.. method:: assertTemplateUsed(response, template_name) +.. method:: TestCase.assertTemplateUsed(response, template_name) Asserts that the template with the given name was used in rendering the response. The name is a string such as ``'admin/index.html'``. -.. method:: assertTemplateNotUsed(response, template_name) +.. method:: TestCase.assertTemplateNotUsed(response, template_name) Asserts that the template with the given name was *not* used in rendering the response. -.. method:: assertRedirects(response, expected_url, status_code=302, target_status_code=200) +.. method:: TestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200) Asserts that the response return a ``status_code`` redirect status, it redirected to ``expected_url`` (including any GET data), and the final |
