Code

Ticket #18033: 18033-3.diff

File 18033-3.diff, 152.9 KB (added by claudep, 2 years ago)

Updated to current trunk

Line 
1From d6f598b2f93e98573656e29c2df3747633d2ade0 Mon Sep 17 00:00:00 2001
2From: Claude Paroz <claude@2xlibre.net>
3Date: Sat, 31 Mar 2012 21:26:00 +0200
4Subject: [PATCH 3/3] Remove function-based generic views
5
6---
7 django/views/generic/create_update.py              |  221 ----
8 django/views/generic/date_based.py                 |  376 -------
9 django/views/generic/list_detail.py                |  152 ---
10 django/views/generic/simple.py                     |   68 --
11 docs/glossary.txt                                  |    2 +-
12 docs/index.txt                                     |    1 -
13 docs/internals/deprecation.txt                     |    2 +-
14 docs/intro/tutorial04.txt                          |    2 +-
15 docs/misc/api-stability.txt                        |    2 +-
16 docs/ref/class-based-views.txt                     |    6 +-
17 docs/ref/contrib/messages.txt                      |    4 -
18 docs/ref/contrib/sitemaps.txt                      |   20 +-
19 docs/ref/generic-views.txt                         | 1112 --------------------
20 docs/ref/index.txt                                 |    8 -
21 docs/releases/1.1-alpha-1.txt                      |    4 +-
22 docs/releases/1.1.txt                              |    4 +-
23 docs/releases/1.3-alpha-1.txt                      |    2 +-
24 docs/releases/1.3.txt                              |    4 +-
25 docs/topics/auth.txt                               |   13 -
26 docs/topics/class-based-views.txt                  |    6 +-
27 docs/topics/generic-views-migration.txt            |  159 ---
28 docs/topics/generic-views.txt                      |  511 ---------
29 docs/topics/http/generic-views.txt                 |    2 +-
30 docs/topics/http/urls.txt                          |   12 +-
31 docs/topics/index.txt                              |    9 -
32 tests/regressiontests/special_headers/tests.py     |   10 -
33 tests/regressiontests/special_headers/urls.py      |    3 +-
34 tests/regressiontests/special_headers/views.py     |    9 +-
35 tests/regressiontests/views/generic_urls.py        |   74 +--
36 tests/regressiontests/views/tests/__init__.py      |    5 -
37 .../views/tests/generic/create_update.py           |  255 -----
38 .../views/tests/generic/date_based.py              |  171 ---
39 .../views/tests/generic/object_list.py             |   47 -
40 .../regressiontests/views/tests/generic/simple.py  |   64 --
41 tests/regressiontests/views/tests/shortcuts.py     |   10 -
42 tests/regressiontests/views/tests/specials.py      |   10 -
43 tests/regressiontests/views/views.py               |   19 -
44 37 files changed, 45 insertions(+), 3334 deletions(-)
45 delete mode 100644 django/views/generic/create_update.py
46 delete mode 100644 django/views/generic/date_based.py
47 delete mode 100644 django/views/generic/list_detail.py
48 delete mode 100644 django/views/generic/simple.py
49 delete mode 100644 docs/ref/generic-views.txt
50 delete mode 100644 docs/topics/generic-views-migration.txt
51 delete mode 100644 docs/topics/generic-views.txt
52 delete mode 100644 tests/regressiontests/views/tests/generic/__init__.py
53 delete mode 100644 tests/regressiontests/views/tests/generic/create_update.py
54 delete mode 100644 tests/regressiontests/views/tests/generic/date_based.py
55 delete mode 100644 tests/regressiontests/views/tests/generic/object_list.py
56 delete mode 100644 tests/regressiontests/views/tests/generic/simple.py
57
58diff --git a/django/views/generic/create_update.py b/django/views/generic/create_update.py
59deleted file mode 100644
60index 59760b4..0000000
61--- a/django/views/generic/create_update.py
62+++ /dev/null
63@@ -1,221 +0,0 @@
64-from django.forms.models import ModelFormMetaclass, ModelForm
65-from django.template import RequestContext, loader
66-from django.http import Http404, HttpResponse, HttpResponseRedirect
67-from django.core.xheaders import populate_xheaders
68-from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
69-from django.utils.translation import ugettext
70-from django.contrib.auth.views import redirect_to_login
71-from django.views.generic import GenericViewError
72-from django.contrib import messages
73-
74-import warnings
75-warnings.warn(
76-    'Function-based generic views have been deprecated; use class-based views instead.',
77-    DeprecationWarning
78-)
79-
80-
81-def apply_extra_context(extra_context, context):
82-    """
83-    Adds items from extra_context dict to context.  If a value in extra_context
84-    is callable, then it is called and the result is added to context.
85-    """
86-    for key, value in extra_context.iteritems():
87-        if callable(value):
88-            context[key] = value()
89-        else:
90-            context[key] = value
91-
92-def get_model_and_form_class(model, form_class):
93-    """
94-    Returns a model and form class based on the model and form_class
95-    parameters that were passed to the generic view.
96-
97-    If ``form_class`` is given then its associated model will be returned along
98-    with ``form_class`` itself.  Otherwise, if ``model`` is given, ``model``
99-    itself will be returned along with a ``ModelForm`` class created from
100-    ``model``.
101-    """
102-    if form_class:
103-        return form_class._meta.model, form_class
104-    if model:
105-        # The inner Meta class fails if model = model is used for some reason.
106-        tmp_model = model
107-        # TODO: we should be able to construct a ModelForm without creating
108-        # and passing in a temporary inner class.
109-        class Meta:
110-            model = tmp_model
111-        class_name = model.__name__ + 'Form'
112-        form_class = ModelFormMetaclass(class_name, (ModelForm,), {'Meta': Meta})
113-        return model, form_class
114-    raise GenericViewError("Generic view must be called with either a model or"
115-                           " form_class argument.")
116-
117-def redirect(post_save_redirect, obj):
118-    """
119-    Returns a HttpResponseRedirect to ``post_save_redirect``.
120-
121-    ``post_save_redirect`` should be a string, and can contain named string-
122-    substitution place holders of ``obj`` field names.
123-
124-    If ``post_save_redirect`` is None, then redirect to ``obj``'s URL returned
125-    by ``get_absolute_url()``.  If ``obj`` has no ``get_absolute_url`` method,
126-    then raise ImproperlyConfigured.
127-
128-    This function is meant to handle the post_save_redirect parameter to the
129-    ``create_object`` and ``update_object`` views.
130-    """
131-    if post_save_redirect:
132-        return HttpResponseRedirect(post_save_redirect % obj.__dict__)
133-    elif hasattr(obj, 'get_absolute_url'):
134-        return HttpResponseRedirect(obj.get_absolute_url())
135-    else:
136-        raise ImproperlyConfigured(
137-            "No URL to redirect to.  Either pass a post_save_redirect"
138-            " parameter to the generic view or define a get_absolute_url"
139-            " method on the Model.")
140-
141-def lookup_object(model, object_id, slug, slug_field):
142-    """
143-    Return the ``model`` object with the passed ``object_id``.  If
144-    ``object_id`` is None, then return the object whose ``slug_field``
145-    equals the passed ``slug``.  If ``slug`` and ``slug_field`` are not passed,
146-    then raise Http404 exception.
147-    """
148-    lookup_kwargs = {}
149-    if object_id:
150-        lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
151-    elif slug and slug_field:
152-        lookup_kwargs['%s__exact' % slug_field] = slug
153-    else:
154-        raise GenericViewError(
155-            "Generic view must be called with either an object_id or a"
156-            " slug/slug_field.")
157-    try:
158-        return model.objects.get(**lookup_kwargs)
159-    except ObjectDoesNotExist:
160-        raise Http404("No %s found for %s"
161-                      % (model._meta.verbose_name, lookup_kwargs))
162-
163-def create_object(request, model=None, template_name=None,
164-        template_loader=loader, extra_context=None, post_save_redirect=None,
165-        login_required=False, context_processors=None, form_class=None):
166-    """
167-    Generic object-creation function.
168-
169-    Templates: ``<app_label>/<model_name>_form.html``
170-    Context:
171-        form
172-            the form for the object
173-    """
174-    if extra_context is None: extra_context = {}
175-    if login_required and not request.user.is_authenticated():
176-        return redirect_to_login(request.path)
177-
178-    model, form_class = get_model_and_form_class(model, form_class)
179-    if request.method == 'POST':
180-        form = form_class(request.POST, request.FILES)
181-        if form.is_valid():
182-            new_object = form.save()
183-
184-            msg = ugettext("The %(verbose_name)s was created successfully.") %\
185-                                    {"verbose_name": model._meta.verbose_name}
186-            messages.success(request, msg, fail_silently=True)
187-            return redirect(post_save_redirect, new_object)
188-    else:
189-        form = form_class()
190-
191-    # Create the template, context, response
192-    if not template_name:
193-        template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower())
194-    t = template_loader.get_template(template_name)
195-    c = RequestContext(request, {
196-        'form': form,
197-    }, context_processors)
198-    apply_extra_context(extra_context, c)
199-    return HttpResponse(t.render(c))
200-
201-def update_object(request, model=None, object_id=None, slug=None,
202-        slug_field='slug', template_name=None, template_loader=loader,
203-        extra_context=None, post_save_redirect=None, login_required=False,
204-        context_processors=None, template_object_name='object',
205-        form_class=None):
206-    """
207-    Generic object-update function.
208-
209-    Templates: ``<app_label>/<model_name>_form.html``
210-    Context:
211-        form
212-            the form for the object
213-        object
214-            the original object being edited
215-    """
216-    if extra_context is None: extra_context = {}
217-    if login_required and not request.user.is_authenticated():
218-        return redirect_to_login(request.path)
219-
220-    model, form_class = get_model_and_form_class(model, form_class)
221-    obj = lookup_object(model, object_id, slug, slug_field)
222-
223-    if request.method == 'POST':
224-        form = form_class(request.POST, request.FILES, instance=obj)
225-        if form.is_valid():
226-            obj = form.save()
227-            msg = ugettext("The %(verbose_name)s was updated successfully.") %\
228-                                    {"verbose_name": model._meta.verbose_name}
229-            messages.success(request, msg, fail_silently=True)
230-            return redirect(post_save_redirect, obj)
231-    else:
232-        form = form_class(instance=obj)
233-
234-    if not template_name:
235-        template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower())
236-    t = template_loader.get_template(template_name)
237-    c = RequestContext(request, {
238-        'form': form,
239-        template_object_name: obj,
240-    }, context_processors)
241-    apply_extra_context(extra_context, c)
242-    response = HttpResponse(t.render(c))
243-    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.attname))
244-    return response
245-
246-def delete_object(request, model, post_delete_redirect, object_id=None,
247-        slug=None, slug_field='slug', template_name=None,
248-        template_loader=loader, extra_context=None, login_required=False,
249-        context_processors=None, template_object_name='object'):
250-    """
251-    Generic object-delete function.
252-
253-    The given template will be used to confirm deletetion if this view is
254-    fetched using GET; for safty, deletion will only be performed if this
255-    view is POSTed.
256-
257-    Templates: ``<app_label>/<model_name>_confirm_delete.html``
258-    Context:
259-        object
260-            the original object being deleted
261-    """
262-    if extra_context is None: extra_context = {}
263-    if login_required and not request.user.is_authenticated():
264-        return redirect_to_login(request.path)
265-
266-    obj = lookup_object(model, object_id, slug, slug_field)
267-
268-    if request.method == 'POST':
269-        obj.delete()
270-        msg = ugettext("The %(verbose_name)s was deleted.") %\
271-                                    {"verbose_name": model._meta.verbose_name}
272-        messages.success(request, msg, fail_silently=True)
273-        return HttpResponseRedirect(post_delete_redirect)
274-    else:
275-        if not template_name:
276-            template_name = "%s/%s_confirm_delete.html" % (model._meta.app_label, model._meta.object_name.lower())
277-        t = template_loader.get_template(template_name)
278-        c = RequestContext(request, {
279-            template_object_name: obj,
280-        }, context_processors)
281-        apply_extra_context(extra_context, c)
282-        response = HttpResponse(t.render(c))
283-        populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.attname))
284-        return response
285diff --git a/django/views/generic/date_based.py b/django/views/generic/date_based.py
286deleted file mode 100644
287index 75094aa..0000000
288--- a/django/views/generic/date_based.py
289+++ /dev/null
290@@ -1,376 +0,0 @@
291-import datetime
292-import time
293-
294-from django.template import loader, RequestContext
295-from django.core.exceptions import ObjectDoesNotExist
296-from django.core.xheaders import populate_xheaders
297-from django.db.models.fields import DateTimeField
298-from django.http import Http404, HttpResponse
299-from django.utils import timezone
300-
301-import warnings
302-warnings.warn(
303-    'Function-based generic views have been deprecated; use class-based views instead.',
304-    DeprecationWarning
305-)
306-
307-
308-def archive_index(request, queryset, date_field, num_latest=15,
309-        template_name=None, template_loader=loader,
310-        extra_context=None, allow_empty=True, context_processors=None,
311-        mimetype=None, allow_future=False, template_object_name='latest'):
312-    """
313-    Generic top-level archive of date-based objects.
314-
315-    Templates: ``<app_label>/<model_name>_archive.html``
316-    Context:
317-        date_list
318-            List of years
319-        latest
320-            Latest N (defaults to 15) objects by date
321-    """
322-    if extra_context is None: extra_context = {}
323-    model = queryset.model
324-    if not allow_future:
325-        queryset = queryset.filter(**{'%s__lte' % date_field: timezone.now()})
326-    date_list = queryset.dates(date_field, 'year')[::-1]
327-    if not date_list and not allow_empty:
328-        raise Http404("No %s available" % model._meta.verbose_name)
329-
330-    if date_list and num_latest:
331-        latest = queryset.order_by('-'+date_field)[:num_latest]
332-    else:
333-        latest = None
334-
335-    if not template_name:
336-        template_name = "%s/%s_archive.html" % (model._meta.app_label, model._meta.object_name.lower())
337-    t = template_loader.get_template(template_name)
338-    c = RequestContext(request, {
339-        'date_list' : date_list,
340-        template_object_name : latest,
341-    }, context_processors)
342-    for key, value in extra_context.items():
343-        if callable(value):
344-            c[key] = value()
345-        else:
346-            c[key] = value
347-    return HttpResponse(t.render(c), mimetype=mimetype)
348-
349-def archive_year(request, year, queryset, date_field, template_name=None,
350-        template_loader=loader, extra_context=None, allow_empty=False,
351-        context_processors=None, template_object_name='object', mimetype=None,
352-        make_object_list=False, allow_future=False):
353-    """
354-    Generic yearly archive view.
355-
356-    Templates: ``<app_label>/<model_name>_archive_year.html``
357-    Context:
358-        date_list
359-            List of months in this year with objects
360-        year
361-            This year
362-        object_list
363-            List of objects published in the given month
364-            (Only available if make_object_list argument is True)
365-    """
366-    if extra_context is None: extra_context = {}
367-    model = queryset.model
368-    now = timezone.now()
369-
370-    lookup_kwargs = {'%s__year' % date_field: year}
371-
372-    # Only bother to check current date if the year isn't in the past and future objects aren't requested.
373-    if int(year) >= now.year and not allow_future:
374-        lookup_kwargs['%s__lte' % date_field] = now
375-    date_list = queryset.filter(**lookup_kwargs).dates(date_field, 'month')
376-    if not date_list and not allow_empty:
377-        raise Http404
378-    if make_object_list:
379-        object_list = queryset.filter(**lookup_kwargs)
380-    else:
381-        object_list = []
382-    if not template_name:
383-        template_name = "%s/%s_archive_year.html" % (model._meta.app_label, model._meta.object_name.lower())
384-    t = template_loader.get_template(template_name)
385-    c = RequestContext(request, {
386-        'date_list': date_list,
387-        'year': year,
388-        '%s_list' % template_object_name: object_list,
389-    }, context_processors)
390-    for key, value in extra_context.items():
391-        if callable(value):
392-            c[key] = value()
393-        else:
394-            c[key] = value
395-    return HttpResponse(t.render(c), mimetype=mimetype)
396-
397-def archive_month(request, year, month, queryset, date_field,
398-        month_format='%b', template_name=None, template_loader=loader,
399-        extra_context=None, allow_empty=False, context_processors=None,
400-        template_object_name='object', mimetype=None, allow_future=False):
401-    """
402-    Generic monthly archive view.
403-
404-    Templates: ``<app_label>/<model_name>_archive_month.html``
405-    Context:
406-        date_list:
407-            List of days in this month with objects
408-        month:
409-            (date) this month
410-        next_month:
411-            (date) the first day of the next month, or None if the next month is in the future
412-        previous_month:
413-            (date) the first day of the previous month
414-        object_list:
415-            list of objects published in the given month
416-    """
417-    if extra_context is None: extra_context = {}
418-    try:
419-        tt = time.strptime("%s-%s" % (year, month), '%s-%s' % ('%Y', month_format))
420-        date = datetime.date(*tt[:3])
421-    except ValueError:
422-        raise Http404
423-
424-    model = queryset.model
425-    now = timezone.now()
426-
427-    # Calculate first and last day of month, for use in a date-range lookup.
428-    first_day = date.replace(day=1)
429-    if first_day.month == 12:
430-        last_day = first_day.replace(year=first_day.year + 1, month=1)
431-    else:
432-        last_day = first_day.replace(month=first_day.month + 1)
433-    lookup_kwargs = {
434-        '%s__gte' % date_field: first_day,
435-        '%s__lt' % date_field: last_day,
436-    }
437-
438-    # Only bother to check current date if the month isn't in the past and future objects are requested.
439-    if last_day >= now.date() and not allow_future:
440-        lookup_kwargs['%s__lte' % date_field] = now
441-    object_list = queryset.filter(**lookup_kwargs)
442-    date_list = object_list.dates(date_field, 'day')
443-    if not object_list and not allow_empty:
444-        raise Http404
445-
446-    # Calculate the next month, if applicable.
447-    if allow_future:
448-        next_month = last_day
449-    elif last_day <= datetime.date.today():
450-        next_month = last_day
451-    else:
452-        next_month = None
453-
454-    # Calculate the previous month
455-    if first_day.month == 1:
456-        previous_month = first_day.replace(year=first_day.year-1,month=12)
457-    else:
458-        previous_month = first_day.replace(month=first_day.month-1)
459-
460-    if not template_name:
461-        template_name = "%s/%s_archive_month.html" % (model._meta.app_label, model._meta.object_name.lower())
462-    t = template_loader.get_template(template_name)
463-    c = RequestContext(request, {
464-        'date_list': date_list,
465-        '%s_list' % template_object_name: object_list,
466-        'month': date,
467-        'next_month': next_month,
468-        'previous_month': previous_month,
469-    }, context_processors)
470-    for key, value in extra_context.items():
471-        if callable(value):
472-            c[key] = value()
473-        else:
474-            c[key] = value
475-    return HttpResponse(t.render(c), mimetype=mimetype)
476-
477-def archive_week(request, year, week, queryset, date_field,
478-        template_name=None, template_loader=loader,
479-        extra_context=None, allow_empty=True, context_processors=None,
480-        template_object_name='object', mimetype=None, allow_future=False):
481-    """
482-    Generic weekly archive view.
483-
484-    Templates: ``<app_label>/<model_name>_archive_week.html``
485-    Context:
486-        week:
487-            (date) this week
488-        object_list:
489-            list of objects published in the given week
490-    """
491-    if extra_context is None: extra_context = {}
492-    try:
493-        tt = time.strptime(year+'-0-'+week, '%Y-%w-%U')
494-        date = datetime.date(*tt[:3])
495-    except ValueError:
496-        raise Http404
497-
498-    model = queryset.model
499-    now = timezone.now()
500-
501-    # Calculate first and last day of week, for use in a date-range lookup.
502-    first_day = date
503-    last_day = date + datetime.timedelta(days=7)
504-    lookup_kwargs = {
505-        '%s__gte' % date_field: first_day,
506-        '%s__lt' % date_field: last_day,
507-    }
508-
509-    # Only bother to check current date if the week isn't in the past and future objects aren't requested.
510-    if last_day >= now.date() and not allow_future:
511-        lookup_kwargs['%s__lte' % date_field] = now
512-    object_list = queryset.filter(**lookup_kwargs)
513-    if not object_list and not allow_empty:
514-        raise Http404
515-    if not template_name:
516-        template_name = "%s/%s_archive_week.html" % (model._meta.app_label, model._meta.object_name.lower())
517-    t = template_loader.get_template(template_name)
518-    c = RequestContext(request, {
519-        '%s_list' % template_object_name: object_list,
520-        'week': date,
521-    })
522-    for key, value in extra_context.items():
523-        if callable(value):
524-            c[key] = value()
525-        else:
526-            c[key] = value
527-    return HttpResponse(t.render(c), mimetype=mimetype)
528-
529-def archive_day(request, year, month, day, queryset, date_field,
530-        month_format='%b', day_format='%d', template_name=None,
531-        template_loader=loader, extra_context=None, allow_empty=False,
532-        context_processors=None, template_object_name='object',
533-        mimetype=None, allow_future=False):
534-    """
535-    Generic daily archive view.
536-
537-    Templates: ``<app_label>/<model_name>_archive_day.html``
538-    Context:
539-        object_list:
540-            list of objects published that day
541-        day:
542-            (datetime) the day
543-        previous_day
544-            (datetime) the previous day
545-        next_day
546-            (datetime) the next day, or None if the current day is today
547-    """
548-    if extra_context is None: extra_context = {}
549-    try:
550-        tt = time.strptime('%s-%s-%s' % (year, month, day),
551-                           '%s-%s-%s' % ('%Y', month_format, day_format))
552-        date = datetime.date(*tt[:3])
553-    except ValueError:
554-        raise Http404
555-
556-    model = queryset.model
557-    now = timezone.now()
558-
559-    if isinstance(model._meta.get_field(date_field), DateTimeField):
560-        lookup_kwargs = {'%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max))}
561-    else:
562-        lookup_kwargs = {date_field: date}
563-
564-    # Only bother to check current date if the date isn't in the past and future objects aren't requested.
565-    if date >= now.date() and not allow_future:
566-        lookup_kwargs['%s__lte' % date_field] = now
567-    object_list = queryset.filter(**lookup_kwargs)
568-    if not allow_empty and not object_list:
569-        raise Http404
570-
571-    # Calculate the next day, if applicable.
572-    if allow_future:
573-        next_day = date + datetime.timedelta(days=1)
574-    elif date < datetime.date.today():
575-        next_day = date + datetime.timedelta(days=1)
576-    else:
577-        next_day = None
578-
579-    if not template_name:
580-        template_name = "%s/%s_archive_day.html" % (model._meta.app_label, model._meta.object_name.lower())
581-    t = template_loader.get_template(template_name)
582-    c = RequestContext(request, {
583-        '%s_list' % template_object_name: object_list,
584-        'day': date,
585-        'previous_day': date - datetime.timedelta(days=1),
586-        'next_day': next_day,
587-    }, context_processors)
588-    for key, value in extra_context.items():
589-        if callable(value):
590-            c[key] = value()
591-        else:
592-            c[key] = value
593-    return HttpResponse(t.render(c), mimetype=mimetype)
594-
595-def archive_today(request, **kwargs):
596-    """
597-    Generic daily archive view for today. Same as archive_day view.
598-    """
599-    today = datetime.date.today()
600-    kwargs.update({
601-        'year': str(today.year),
602-        'month': today.strftime('%b').lower(),
603-        'day': str(today.day),
604-    })
605-    return archive_day(request, **kwargs)
606-
607-def object_detail(request, year, month, day, queryset, date_field,
608-        month_format='%b', day_format='%d', object_id=None, slug=None,
609-        slug_field='slug', template_name=None, template_name_field=None,
610-        template_loader=loader, extra_context=None, context_processors=None,
611-        template_object_name='object', mimetype=None, allow_future=False):
612-    """
613-    Generic detail view from year/month/day/slug or year/month/day/id structure.
614-
615-    Templates: ``<app_label>/<model_name>_detail.html``
616-    Context:
617-        object:
618-            the object to be detailed
619-    """
620-    if extra_context is None: extra_context = {}
621-    try:
622-        tt = time.strptime('%s-%s-%s' % (year, month, day),
623-                           '%s-%s-%s' % ('%Y', month_format, day_format))
624-        date = datetime.date(*tt[:3])
625-    except ValueError:
626-        raise Http404
627-
628-    model = queryset.model
629-    now = timezone.now()
630-
631-    if isinstance(model._meta.get_field(date_field), DateTimeField):
632-        lookup_kwargs = {'%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max))}
633-    else:
634-        lookup_kwargs = {date_field: date}
635-
636-    # Only bother to check current date if the date isn't in the past and future objects aren't requested.
637-    if date >= now.date() and not allow_future:
638-        lookup_kwargs['%s__lte' % date_field] = now
639-    if object_id:
640-        lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
641-    elif slug and slug_field:
642-        lookup_kwargs['%s__exact' % slug_field] = slug
643-    else:
644-        raise AttributeError("Generic detail view must be called with either an object_id or a slug/slugfield")
645-    try:
646-        obj = queryset.get(**lookup_kwargs)
647-    except ObjectDoesNotExist:
648-        raise Http404("No %s found for" % model._meta.verbose_name)
649-    if not template_name:
650-        template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower())
651-    if template_name_field:
652-        template_name_list = [getattr(obj, template_name_field), template_name]
653-        t = template_loader.select_template(template_name_list)
654-    else:
655-        t = template_loader.get_template(template_name)
656-    c = RequestContext(request, {
657-        template_object_name: obj,
658-    }, context_processors)
659-    for key, value in extra_context.items():
660-        if callable(value):
661-            c[key] = value()
662-        else:
663-            c[key] = value
664-    response = HttpResponse(t.render(c), mimetype=mimetype)
665-    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
666-    return response
667diff --git a/django/views/generic/list_detail.py b/django/views/generic/list_detail.py
668deleted file mode 100644
669index 22414ae..0000000
670--- a/django/views/generic/list_detail.py
671+++ /dev/null
672@@ -1,152 +0,0 @@
673-from django.template import loader, RequestContext
674-from django.http import Http404, HttpResponse
675-from django.core.xheaders import populate_xheaders
676-from django.core.paginator import Paginator, InvalidPage
677-from django.core.exceptions import ObjectDoesNotExist
678-
679-import warnings
680-warnings.warn(
681-    'Function-based generic views have been deprecated; use class-based views instead.',
682-    DeprecationWarning
683-)
684-
685-
686-def object_list(request, queryset, paginate_by=None, page=None,
687-        allow_empty=True, template_name=None, template_loader=loader,
688-        extra_context=None, context_processors=None, template_object_name='object',
689-        mimetype=None):
690-    """
691-    Generic list of objects.
692-
693-    Templates: ``<app_label>/<model_name>_list.html``
694-    Context:
695-        object_list
696-            list of objects
697-        is_paginated
698-            are the results paginated?
699-        results_per_page
700-            number of objects per page (if paginated)
701-        has_next
702-            is there a next page?
703-        has_previous
704-            is there a prev page?
705-        page
706-            the current page
707-        next
708-            the next page
709-        previous
710-            the previous page
711-        pages
712-            number of pages, total
713-        hits
714-            number of objects, total
715-        last_on_page
716-            the result number of the last of object in the
717-            object_list (1-indexed)
718-        first_on_page
719-            the result number of the first object in the
720-            object_list (1-indexed)
721-        page_range:
722-            A list of the page numbers (1-indexed).
723-    """
724-    if extra_context is None: extra_context = {}
725-    queryset = queryset._clone()
726-    if paginate_by:
727-        paginator = Paginator(queryset, paginate_by, allow_empty_first_page=allow_empty)
728-        if not page:
729-            page = request.GET.get('page', 1)
730-        try:
731-            page_number = int(page)
732-        except ValueError:
733-            if page == 'last':
734-                page_number = paginator.num_pages
735-            else:
736-                # Page is not 'last', nor can it be converted to an int.
737-                raise Http404
738-        try:
739-            page_obj = paginator.page(page_number)
740-        except InvalidPage:
741-            raise Http404
742-        c = RequestContext(request, {
743-            '%s_list' % template_object_name: page_obj.object_list,
744-            'paginator': paginator,
745-            'page_obj': page_obj,
746-            'is_paginated': page_obj.has_other_pages(),
747-
748-            # Legacy template context stuff. New templates should use page_obj
749-            # to access this instead.
750-            'results_per_page': paginator.per_page,
751-            'has_next': page_obj.has_next(),
752-            'has_previous': page_obj.has_previous(),
753-            'page': page_obj.number,
754-            'next': page_obj.next_page_number(),
755-            'previous': page_obj.previous_page_number(),
756-            'first_on_page': page_obj.start_index(),
757-            'last_on_page': page_obj.end_index(),
758-            'pages': paginator.num_pages,
759-            'hits': paginator.count,
760-            'page_range': paginator.page_range,
761-        }, context_processors)
762-    else:
763-        c = RequestContext(request, {
764-            '%s_list' % template_object_name: queryset,
765-            'paginator': None,
766-            'page_obj': None,
767-            'is_paginated': False,
768-        }, context_processors)
769-        if not allow_empty and len(queryset) == 0:
770-            raise Http404
771-    for key, value in extra_context.items():
772-        if callable(value):
773-            c[key] = value()
774-        else:
775-            c[key] = value
776-    if not template_name:
777-        model = queryset.model
778-        template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower())
779-    t = template_loader.get_template(template_name)
780-    return HttpResponse(t.render(c), mimetype=mimetype)
781-
782-def object_detail(request, queryset, object_id=None, slug=None,
783-        slug_field='slug', template_name=None, template_name_field=None,
784-        template_loader=loader, extra_context=None,
785-        context_processors=None, template_object_name='object',
786-        mimetype=None):
787-    """
788-    Generic detail of an object.
789-
790-    Templates: ``<app_label>/<model_name>_detail.html``
791-    Context:
792-        object
793-            the object
794-    """
795-    if extra_context is None: extra_context = {}
796-    model = queryset.model
797-    if object_id:
798-        queryset = queryset.filter(pk=object_id)
799-    elif slug and slug_field:
800-        queryset = queryset.filter(**{slug_field: slug})
801-    else:
802-        raise AttributeError("Generic detail view must be called with either an object_id or a slug/slug_field.")
803-    try:
804-        obj = queryset.get()
805-    except ObjectDoesNotExist:
806-        raise Http404("No %s found matching the query" % (model._meta.verbose_name))
807-    if not template_name:
808-        template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower())
809-    if template_name_field:
810-        template_name_list = [getattr(obj, template_name_field), template_name]
811-        t = template_loader.select_template(template_name_list)
812-    else:
813-        t = template_loader.get_template(template_name)
814-    c = RequestContext(request, {
815-        template_object_name: obj,
816-    }, context_processors)
817-    for key, value in extra_context.items():
818-        if callable(value):
819-            c[key] = value()
820-        else:
821-            c[key] = value
822-    response = HttpResponse(t.render(c), mimetype=mimetype)
823-    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
824-    return response
825diff --git a/django/views/generic/simple.py b/django/views/generic/simple.py
826deleted file mode 100644
827index f63860a..0000000
828--- a/django/views/generic/simple.py
829+++ /dev/null
830@@ -1,68 +0,0 @@
831-from django.template import loader, RequestContext
832-from django.http import HttpResponse, HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponseGone
833-from django.utils.log import getLogger
834-
835-import warnings
836-warnings.warn(
837-    'Function-based generic views have been deprecated; use class-based views instead.',
838-    DeprecationWarning
839-)
840-
841-logger = getLogger('django.request')
842-
843-
844-def direct_to_template(request, template, extra_context=None, mimetype=None, **kwargs):
845-    """
846-    Render a given template with any extra URL parameters in the context as
847-    ``{{ params }}``.
848-    """
849-    if extra_context is None: extra_context = {}
850-    dictionary = {'params': kwargs}
851-    for key, value in extra_context.items():
852-        if callable(value):
853-            dictionary[key] = value()
854-        else:
855-            dictionary[key] = value
856-    c = RequestContext(request, dictionary)
857-    t = loader.get_template(template)
858-    return HttpResponse(t.render(c), content_type=mimetype)
859-
860-def redirect_to(request, url, permanent=True, query_string=False, **kwargs):
861-    """
862-    Redirect to a given URL.
863-
864-    The given url may contain dict-style string formatting, which will be
865-    interpolated against the params in the URL.  For example, to redirect from
866-    ``/foo/<id>/`` to ``/bar/<id>/``, you could use the following URLconf::
867-
868-        urlpatterns = patterns('',
869-            ('^foo/(?P<id>\d+)/$', 'django.views.generic.simple.redirect_to', {'url' : '/bar/%(id)s/'}),
870-        )
871-
872-    If the given url is ``None``, a HttpResponseGone (410) will be issued.
873-
874-    If the ``permanent`` argument is False, then the response will have a 302
875-    HTTP status code. Otherwise, the status code will be 301.
876-
877-    If the ``query_string`` argument is True, then the GET query string
878-    from the request is appended to the URL.
879-
880-    """
881-    args = request.META.get('QUERY_STRING', '')
882-
883-    if url is not None:
884-        if kwargs:
885-            url = url % kwargs
886-
887-        if args and query_string:
888-            url = "%s?%s" % (url, args)
889-
890-        klass = permanent and HttpResponsePermanentRedirect or HttpResponseRedirect
891-        return klass(url)
892-    else:
893-        logger.warning('Gone: %s', request.path,
894-                    extra={
895-                        'status_code': 410,
896-                        'request': request
897-                    })
898-        return HttpResponseGone()
899diff --git a/docs/glossary.txt b/docs/glossary.txt
900index 15776ce..4d0f8b9 100644
901--- a/docs/glossary.txt
902+++ b/docs/glossary.txt
903@@ -16,7 +16,7 @@ Glossary
904         A higher-order :term:`view` function that provides an abstract/generic
905         implementation of a common idiom or pattern found in view development.
906 
907-        See :doc:`/ref/generic-views`.
908+        See :doc:`/ref/class-based-views`.
909 
910     model
911         Models store your application's data.
912diff --git a/docs/index.txt b/docs/index.txt
913index 66c8e73..d596511 100644
914--- a/docs/index.txt
915+++ b/docs/index.txt
916@@ -195,7 +195,6 @@ Other batteries included
917 * :doc:`Unicode in Django <ref/unicode>`
918 * :doc:`Web design helpers <ref/contrib/webdesign>`
919 * :doc:`Validators <ref/validators>`
920-* Function-based generic views (Deprecated) :doc:`Overview<topics/generic-views>` | :doc:`Built-in generic views<ref/generic-views>` | :doc:`Migration guide<topics/generic-views-migration>`
921 
922 The Django open-source project
923 ==============================
924diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
925index e54adf0..e3a5e1a 100644
926--- a/docs/internals/deprecation.txt
927+++ b/docs/internals/deprecation.txt
928@@ -134,7 +134,7 @@ these changes.
929 
930 * The function-based generic view modules will be removed in favor of their
931   class-based equivalents, outlined :doc:`here
932-  </topics/generic-views-migration>`:
933+  </topics/class-based-views>`:
934 
935 * The :class:`~django.core.servers.basehttp.AdminMediaHandler` will be
936   removed.  In its place use
937diff --git a/docs/intro/tutorial04.txt b/docs/intro/tutorial04.txt
938index 85d54c3..8a9f4ee 100644
939--- a/docs/intro/tutorial04.txt
940+++ b/docs/intro/tutorial04.txt
941@@ -320,7 +320,7 @@ function anymore -- generic views can be (and are) used multiple times
942 Run the server, and use your new polling app based on generic views.
943 
944 For full details on generic views, see the :doc:`generic views documentation
945-</topics/http/generic-views>`.
946+</topics/class-based-views>`.
947 
948 Coming soon
949 ===========
950diff --git a/docs/misc/api-stability.txt b/docs/misc/api-stability.txt
951index 75fa6b4..5517026 100644
952--- a/docs/misc/api-stability.txt
953+++ b/docs/misc/api-stability.txt
954@@ -54,7 +54,7 @@ of 1.0. This includes these APIs:
955 - :doc:`HTTP request/response handling </topics/http/index>`, including file
956   uploads, middleware, sessions, URL resolution, view, and shortcut APIs.
957 
958-- :doc:`Generic views </topics/http/generic-views>`.
959+- :doc:`Generic views </topics/class-based-views>`.
960 
961 - :doc:`Internationalization </topics/i18n/index>`.
962 
963diff --git a/docs/ref/class-based-views.txt b/docs/ref/class-based-views.txt
964index 5223aee..aa3f8f7 100644
965--- a/docs/ref/class-based-views.txt
966+++ b/docs/ref/class-based-views.txt
967@@ -6,13 +6,9 @@ Class-based generic views
968 
969 .. note::
970     Prior to Django 1.3, generic views were implemented as functions. The
971-    function-based implementation has been deprecated in favor of the
972+    function-based implementation has been removed in favor of the
973     class-based approach described here.
974 
975-    For details on the previous generic views implementation,
976-    see the :doc:`topic guide </topics/generic-views>` and
977-    :doc:`detailed reference </ref/generic-views>`.
978-
979 Writing Web applications can be monotonous, because we repeat certain patterns
980 again and again. Django tries to take away some of that monotony at the model
981 and template layers, but Web developers also experience this boredom at the view
982diff --git a/docs/ref/contrib/messages.txt b/docs/ref/contrib/messages.txt
983index 223a162..4ab9734 100644
984--- a/docs/ref/contrib/messages.txt
985+++ b/docs/ref/contrib/messages.txt
986@@ -274,10 +274,6 @@ example::
987                          fail_silently=True)
988     messages.info(request, 'Hello world.', fail_silently=True)
989 
990-Internally, Django uses this functionality in the create, update, and delete
991-:doc:`generic views </topics/http/generic-views>` so that they work even if the
992-message framework is disabled.
993-
994 .. note::
995    Setting ``fail_silently=True`` only hides the ``MessageFailure`` that would
996    otherwise occur when the messages framework disabled and one attempts to
997diff --git a/docs/ref/contrib/sitemaps.txt b/docs/ref/contrib/sitemaps.txt
998index 64400bc..d775092 100644
999--- a/docs/ref/contrib/sitemaps.txt
1000+++ b/docs/ref/contrib/sitemaps.txt
1001@@ -240,16 +240,16 @@ The sitemap framework provides a couple convenience classes for common cases:
1002 
1003 .. class:: GenericSitemap
1004 
1005-    The :class:`django.contrib.sitemaps.GenericSitemap` class works with any
1006-    :doc:`generic views </ref/generic-views>` you already have.
1007-    To use it, create an instance, passing in the same :data:`info_dict` you pass to
1008-    the generic views. The only requirement is that the dictionary have a
1009-    :data:`queryset` entry. It may also have a :data:`date_field` entry that specifies a
1010-    date field for objects retrieved from the :data:`queryset`. This will be used for
1011-    the :attr:`~Sitemap.lastmod` attribute in the generated sitemap. You may
1012-    also pass :attr:`~Sitemap.priority` and :attr:`~Sitemap.changefreq`
1013-    keyword arguments to the :class:`~django.contrib.sitemaps.GenericSitemap`
1014-    constructor to specify these attributes for all URLs.
1015+    The :class:`django.contrib.sitemaps.GenericSitemap` class allows you to
1016+    create a sitemap by passing it a dictionary which has to contain at least
1017+    a :data:`queryset` entry. This queryset will be used to generate the items
1018+    of the sitemap. It may also have a :data:`date_field` entry that
1019+    specifies a date field for objects retrieved from the :data:`queryset`.
1020+    This will be used for the :attr:`~Sitemap.lastmod` attribute in the
1021+    generated sitemap. You may also pass :attr:`~Sitemap.priority` and
1022+    :attr:`~Sitemap.changefreq` keyword arguments to the
1023+    :class:`~django.contrib.sitemaps.GenericSitemap`  constructor to specify
1024+    these attributes for all URLs.
1025 
1026 Example
1027 -------
1028diff --git a/docs/ref/generic-views.txt b/docs/ref/generic-views.txt
1029deleted file mode 100644
1030index eb65107..0000000
1031--- a/docs/ref/generic-views.txt
1032+++ /dev/null
1033@@ -1,1112 +0,0 @@
1034-=============
1035-Generic views
1036-=============
1037-
1038-
1039-.. versionchanged:: 1.3
1040-
1041-.. note::
1042-
1043-    From Django 1.3, function-based generic views have been deprecated in favor
1044-    of a class-based approach, described in the class-based views :doc:`topic
1045-    guide </topics/class-based-views>` and :doc:`detailed reference
1046-    </ref/class-based-views>`.
1047-
1048-Writing Web applications can be monotonous, because we repeat certain patterns
1049-again and again. In Django, the most common of these patterns have been
1050-abstracted into "generic views" that let you quickly provide common views of
1051-an object without actually needing to write any Python code.
1052-
1053-A general introduction to generic views can be found in the :doc:`topic guide
1054-</topics/generic-views>`.
1055-
1056-This reference contains details of Django's built-in generic views, along with
1057-a list of all keyword arguments that a generic view expects. Remember that
1058-arguments may either come from the URL pattern or from the ``extra_context``
1059-additional-information dictionary.
1060-
1061-Most generic views require the ``queryset`` key, which is a ``QuerySet``
1062-instance; see :doc:`/topics/db/queries` for more information about ``QuerySet``
1063-objects.
1064-
1065-.. module:: django.views.generic.simple
1066-
1067-"Simple" generic views
1068-======================
1069-
1070-The ``django.views.generic.simple`` module contains simple views to handle a
1071-couple of common cases: rendering a template when no view logic is needed,
1072-and issuing a redirect.
1073-
1074-``django.views.generic.simple.direct_to_template``
1075---------------------------------------------------
1076-
1077-**Description:**
1078-
1079-Renders a given template, passing it a ``{{ params }}`` template variable,
1080-which is a dictionary of the parameters captured in the URL.
1081-
1082-**Required arguments:**
1083-
1084-* ``template``: The full name of a template to use.
1085-
1086-**Optional arguments:**
1087-
1088-* ``extra_context``: A dictionary of values to add to the template
1089-  context. By default, this is an empty dictionary. If a value in the
1090-  dictionary is callable, the generic view will call it
1091-  just before rendering the template.
1092-
1093-* ``mimetype``: The MIME type to use for the resulting document. Defaults
1094-  to the value of the :setting:`DEFAULT_CONTENT_TYPE` setting.
1095-
1096-**Example:**
1097-
1098-Given the following URL patterns::
1099-
1100-    from django.views.generic.simple import direct_to_template
1101-
1102-    urlpatterns = patterns('',
1103-        (r'^foo/$',             direct_to_template, {'template': 'foo_index.html'}),
1104-        (r'^foo/(?P<id>\d+)/$', direct_to_template, {'template': 'foo_detail.html'}),
1105-    )
1106-
1107-... a request to ``/foo/`` would render the template ``foo_index.html``, and a
1108-request to ``/foo/15/`` would render the ``foo_detail.html`` with a context
1109-variable ``{{ params.id }}`` that is set to ``15``.
1110-
1111-``django.views.generic.simple.redirect_to``
1112--------------------------------------------
1113-
1114-**Description:**
1115-
1116-Redirects to a given URL.
1117-
1118-The given URL may contain dictionary-style string formatting, which will be
1119-interpolated against the parameters captured in the URL. Because keyword
1120-interpolation is *always* done (even if no arguments are passed in), any ``"%"``
1121-characters in the URL must be written as ``"%%"`` so that Python will convert
1122-them to a single percent sign on output.
1123-
1124-If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410).
1125-
1126-**Required arguments:**
1127-
1128-* ``url``: The URL to redirect to, as a string. Or ``None`` to raise a 410
1129-  (Gone) HTTP error.
1130-
1131-**Optional arguments:**
1132-
1133-* ``permanent``: Whether the redirect should be permanent. The only
1134-  difference here is the HTTP status code returned. If ``True``, then the
1135-  redirect will use status code 301. If ``False``, then the redirect will
1136-  use status code 302. By default, ``permanent`` is ``True``.
1137-
1138-* ``query_string``: Whether to pass along the GET query string to
1139-  the new location. If ``True``, then the query string is appended
1140-  to the URL. If ``False``, then the query string is discarded. By
1141-  default, ``query_string`` is ``False``.
1142-
1143-.. versionadded:: 1.3
1144-    The ``query_string`` keyword argument is new in Django 1.3.
1145-
1146-**Example:**
1147-
1148-This example issues a permanent redirect (HTTP status code 301) from
1149-``/foo/<id>/`` to ``/bar/<id>/``::
1150-
1151-    from django.views.generic.simple import redirect_to
1152-
1153-    urlpatterns = patterns('',
1154-        ('^foo/(?P<id>\d+)/$', redirect_to, {'url': '/bar/%(id)s/'}),
1155-    )
1156-
1157-This example issues a non-permanent redirect (HTTP status code 302) from
1158-``/foo/<id>/`` to ``/bar/<id>/``::
1159-
1160-    from django.views.generic.simple import redirect_to
1161-
1162-    urlpatterns = patterns('',
1163-        ('^foo/(?P<id>\d+)/$', redirect_to, {'url': '/bar/%(id)s/', 'permanent': False}),
1164-    )
1165-
1166-This example returns a 410 HTTP error for requests to ``/bar/``::
1167-
1168-    from django.views.generic.simple import redirect_to
1169-
1170-    urlpatterns = patterns('',
1171-        ('^bar/$', redirect_to, {'url': None}),
1172-    )
1173-
1174-This example shows how ``"%"`` characters must be written in the URL in order
1175-to avoid confusion with Python's string formatting markers. If the redirect
1176-string is written as ``"%7Ejacob/"`` (with only a single ``%``), an exception would be raised::
1177-
1178-    from django.views.generic.simple import redirect_to
1179-
1180-    urlpatterns = patterns('',
1181-        ('^bar/$', redirect_to, {'url': '%%7Ejacob.'}),
1182-    )
1183-
1184-.. module:: django.views.generic.date_based
1185-
1186-Date-based generic views
1187-========================
1188-
1189-Date-based generic views (in the module ``django.views.generic.date_based``)
1190-are views for displaying drilldown pages for date-based data.
1191-
1192-``django.views.generic.date_based.archive_index``
1193--------------------------------------------------
1194-
1195-**Description:**
1196-
1197-A top-level index page showing the "latest" objects, by date. Objects with
1198-a date in the *future* are not included unless you set ``allow_future`` to
1199-``True``.
1200-
1201-**Required arguments:**
1202-
1203-* ``queryset``: A ``QuerySet`` of objects for which the archive serves.
1204-
1205-* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
1206-  the ``QuerySet``'s model that the date-based archive should use to
1207-  determine the objects on the page.
1208-
1209-**Optional arguments:**
1210-
1211-* ``num_latest``: The number of latest objects to send to the template
1212-  context. By default, it's 15.
1213-
1214-* ``template_name``: The full name of a template to use in rendering the
1215-  page. This lets you override the default template name (see below).
1216-
1217-* ``template_loader``: The template loader to use when loading the
1218-  template. By default, it's ``django.template.loader``.
1219-
1220-* ``extra_context``: A dictionary of values to add to the template
1221-  context. By default, this is an empty dictionary. If a value in the
1222-  dictionary is callable, the generic view will call it
1223-  just before rendering the template.
1224-
1225-* ``allow_empty``: A boolean specifying whether to display the page if no
1226-  objects are available. If this is ``False`` and no objects are available,
1227-  the view will raise a 404 instead of displaying an empty page. By
1228-  default, this is ``True``.
1229-
1230-* ``context_processors``: A list of template-context processors to apply to
1231-  the view's template.
1232-
1233-* ``mimetype``: The MIME type to use for the resulting document. Defaults
1234-  to the value of the :setting:`DEFAULT_CONTENT_TYPE` setting.
1235-
1236-* ``allow_future``: A boolean specifying whether to include "future"
1237-  objects on this page, where "future" means objects in which the field
1238-  specified in ``date_field`` is greater than the current date/time. By
1239-  default, this is ``False``.
1240-
1241-* ``template_object_name``: Designates the name of the template variable
1242-  to use in the template context. By default, this is ``'latest'``.
1243-
1244-**Template name:**
1245-
1246-If ``template_name`` isn't specified, this view will use the template
1247-``<app_label>/<model_name>_archive.html`` by default, where:
1248-
1249-* ``<model_name>`` is your model's name in all lowercase. For a model
1250-  ``StaffMember``, that'd be ``staffmember``.
1251-
1252-* ``<app_label>`` is the right-most part of the full Python path to
1253-  your model's app. For example, if your model lives in
1254-  ``apps/blog/models.py``, that'd be ``blog``.
1255-
1256-**Template context:**
1257-
1258-In addition to ``extra_context``, the template's context will be:
1259-
1260-* ``date_list``: A ``DateQuerySet`` object containing all years that have
1261-  have objects available according to ``queryset``, represented as
1262-  ``datetime.datetime`` objects. These are ordered in reverse. This is
1263-  equivalent to ``queryset.dates(date_field, 'year')[::-1]``.
1264-
1265-* ``latest``: The ``num_latest`` objects in the system, ordered descending
1266-  by ``date_field``. For example, if ``num_latest`` is ``10``, then
1267-  ``latest`` will be a list of the latest 10 objects in ``queryset``.
1268-
1269-  This variable's name depends on the ``template_object_name`` parameter,
1270-  which is ``'latest'`` by default. If ``template_object_name`` is
1271-  ``'foo'``, this variable's name will be ``foo``.
1272-
1273-``django.views.generic.date_based.archive_year``
1274-------------------------------------------------
1275-
1276-**Description:**
1277-
1278-A yearly archive page showing all available months in a given year. Objects
1279-with a date in the *future* are not displayed unless you set ``allow_future``
1280-to ``True``.
1281-
1282-**Required arguments:**
1283-
1284-* ``year``: The four-digit year for which the archive serves.
1285-
1286-* ``queryset``: A ``QuerySet`` of objects for which the archive serves.
1287-
1288-* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
1289-  the ``QuerySet``'s model that the date-based archive should use to
1290-  determine the objects on the page.
1291-
1292-**Optional arguments:**
1293-
1294-* ``template_name``: The full name of a template to use in rendering the
1295-  page. This lets you override the default template name (see below).
1296-
1297-* ``template_loader``: The template loader to use when loading the
1298-  template. By default, it's ``django.template.loader``.
1299-
1300-* ``extra_context``: A dictionary of values to add to the template
1301-  context. By default, this is an empty dictionary. If a value in the
1302-  dictionary is callable, the generic view will call it
1303-  just before rendering the template.
1304-
1305-* ``allow_empty``: A boolean specifying whether to display the page if no
1306-  objects are available. If this is ``False`` and no objects are available,
1307-  the view will raise a 404 instead of displaying an empty page. By
1308-  default, this is ``False``.
1309-
1310-* ``context_processors``: A list of template-context processors to apply to
1311-  the view's template.
1312-
1313-* ``template_object_name``:  Designates the name of the template variable
1314-  to use in the template context. By default, this is ``'object'``. The
1315-  view will append ``'_list'`` to the value of this parameter in
1316-  determining the variable's name.
1317-
1318-* ``make_object_list``: A boolean specifying whether to retrieve the full
1319-  list of objects for this year and pass those to the template. If ``True``,
1320-  this list of objects will be made available to the template as
1321-  ``object_list``. (The name ``object_list`` may be different; see the docs
1322-  for ``object_list`` in the "Template context" section below.) By default,
1323-  this is ``False``.
1324-
1325-* ``mimetype``: The MIME type to use for the resulting document. Defaults
1326-  to the value of the :setting:`DEFAULT_CONTENT_TYPE` setting.
1327-
1328-* ``allow_future``: A boolean specifying whether to include "future"
1329-  objects on this page, where "future" means objects in which the field
1330-  specified in ``date_field`` is greater than the current date/time. By
1331-  default, this is ``False``.
1332-
1333-**Template name:**
1334-
1335-If ``template_name`` isn't specified, this view will use the template
1336-``<app_label>/<model_name>_archive_year.html`` by default.
1337-
1338-**Template context:**
1339-
1340-In addition to ``extra_context``, the template's context will be:
1341-
1342-* ``date_list``: A ``DateQuerySet`` object containing all months that have
1343-  have objects available according to ``queryset``, represented as
1344-  ``datetime.datetime`` objects, in ascending order.
1345-
1346-* ``year``: The given year, as a four-character string.
1347-
1348-* ``object_list``: If the ``make_object_list`` parameter is ``True``, this
1349-  will be set to a list of objects available for the given year, ordered by
1350-  the date field. This variable's name depends on the
1351-  ``template_object_name`` parameter, which is ``'object'`` by default. If
1352-  ``template_object_name`` is ``'foo'``, this variable's name will be
1353-  ``foo_list``.
1354-
1355-  If ``make_object_list`` is ``False``, ``object_list`` will be passed to
1356-  the template as an empty list.
1357-
1358-``django.views.generic.date_based.archive_month``
1359--------------------------------------------------
1360-
1361-**Description:**
1362-
1363-A monthly archive page showing all objects in a given month. Objects with a
1364-date in the *future* are not displayed unless you set ``allow_future`` to
1365-``True``.
1366-
1367-**Required arguments:**
1368-
1369-* ``year``: The four-digit year for which the archive serves (a string).
1370-
1371-* ``month``: The month for which the archive serves, formatted according to
1372-  the ``month_format`` argument.
1373-
1374-* ``queryset``: A ``QuerySet`` of objects for which the archive serves.
1375-
1376-* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
1377-  the ``QuerySet``'s model that the date-based archive should use to
1378-  determine the objects on the page.
1379-
1380-**Optional arguments:**
1381-
1382-* ``month_format``: A format string that regulates what format the ``month``
1383-  parameter uses. This should be in the syntax accepted by Python's
1384-  :func:`~time.strftime`. It's set to ``"%b"`` by default, which is a
1385-  three-letter month abbreviation. To change it to use numbers, use
1386-  ``"%m"``.
1387-
1388-* ``template_name``: The full name of a template to use in rendering the
1389-  page. This lets you override the default template name (see below).
1390-
1391-* ``template_loader``: The template loader to use when loading the
1392-  template. By default, it's ``django.template.loader``.
1393-
1394-* ``extra_context``: A dictionary of values to add to the template
1395-  context. By default, this is an empty dictionary. If a value in the
1396-  dictionary is callable, the generic view will call it
1397-  just before rendering the template.
1398-
1399-* ``allow_empty``: A boolean specifying whether to display the page if no
1400-  objects are available. If this is ``False`` and no objects are available,
1401-  the view will raise a 404 instead of displaying an empty page. By
1402-  default, this is ``False``.
1403-
1404-* ``context_processors``: A list of template-context processors to apply to
1405-  the view's template.
1406-
1407-* ``template_object_name``:  Designates the name of the template variable
1408-  to use in the template context. By default, this is ``'object'``. The
1409-  view will append ``'_list'`` to the value of this parameter in
1410-  determining the variable's name.
1411-
1412-* ``mimetype``: The MIME type to use for the resulting document. Defaults
1413-  to the value of the :setting:`DEFAULT_CONTENT_TYPE` setting.
1414-
1415-* ``allow_future``: A boolean specifying whether to include "future"
1416-  objects on this page, where "future" means objects in which the field
1417-  specified in ``date_field`` is greater than the current date/time. By
1418-  default, this is ``False``.
1419-
1420-**Template name:**
1421-
1422-If ``template_name`` isn't specified, this view will use the template
1423-``<app_label>/<model_name>_archive_month.html`` by default.
1424-
1425-**Template context:**
1426-
1427-.. versionadded:: 1.2
1428-   The inclusion of ``date_list`` in the template's context is new.
1429-
1430-In addition to ``extra_context``, the template's context will be:
1431-
1432-* ``date_list``: A ``DateQuerySet`` object containing all days that have
1433-  have objects available in the given month, according to ``queryset``,
1434-  represented as ``datetime.datetime`` objects, in ascending order.
1435-
1436-* ``month``: A ``datetime.date`` object representing the given month.
1437-
1438-* ``next_month``: A ``datetime.date`` object representing the first day of
1439-  the next month. If the next month is in the future, this will be
1440-  ``None``.
1441-
1442-* ``previous_month``: A ``datetime.date`` object representing the first day
1443-  of the previous month. Unlike ``next_month``, this will never be
1444-  ``None``.
1445-
1446-* ``object_list``: A list of objects available for the given month. This
1447-  variable's name depends on the ``template_object_name`` parameter, which
1448-  is ``'object'`` by default. If ``template_object_name`` is ``'foo'``,
1449-  this variable's name will be ``foo_list``.
1450-
1451-``django.views.generic.date_based.archive_week``
1452-------------------------------------------------
1453-
1454-**Description:**
1455-
1456-A weekly archive page showing all objects in a given week. Objects with a date
1457-in the *future* are not displayed unless you set ``allow_future`` to ``True``.
1458-
1459-**Required arguments:**
1460-
1461-* ``year``: The four-digit year for which the archive serves (a string).
1462-
1463-* ``week``: The week of the year for which the archive serves (a string).
1464-  Weeks start with Sunday.
1465-
1466-* ``queryset``: A ``QuerySet`` of objects for which the archive serves.
1467-
1468-* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
1469-  the ``QuerySet``'s model that the date-based archive should use to
1470-  determine the objects on the page.
1471-
1472-**Optional arguments:**
1473-
1474-* ``template_name``: The full name of a template to use in rendering the
1475-  page. This lets you override the default template name (see below).
1476-
1477-* ``template_loader``: The template loader to use when loading the
1478-  template. By default, it's ``django.template.loader``.
1479-
1480-* ``extra_context``: A dictionary of values to add to the template
1481-  context. By default, this is an empty dictionary. If a value in the
1482-  dictionary is callable, the generic view will call it
1483-  just before rendering the template.
1484-
1485-* ``allow_empty``: A boolean specifying whether to display the page if no
1486-  objects are available. If this is ``False`` and no objects are available,
1487-  the view will raise a 404 instead of displaying an empty page. By
1488-  default, this is ``True``.
1489-
1490-* ``context_processors``: A list of template-context processors to apply to
1491-  the view's template.
1492-
1493-* ``template_object_name``:  Designates the name of the template variable
1494-  to use in the template context. By default, this is ``'object'``. The
1495-  view will append ``'_list'`` to the value of this parameter in
1496-  determining the variable's name.
1497-
1498-* ``mimetype``: The MIME type to use for the resulting document. Defaults
1499-  to the value of the :setting:`DEFAULT_CONTENT_TYPE` setting.
1500-
1501-* ``allow_future``: A boolean specifying whether to include "future"
1502-  objects on this page, where "future" means objects in which the field
1503-  specified in ``date_field`` is greater than the current date/time. By
1504-  default, this is ``False``.
1505-
1506-**Template name:**
1507-
1508-If ``template_name`` isn't specified, this view will use the template
1509-``<app_label>/<model_name>_archive_week.html`` by default.
1510-
1511-**Template context:**
1512-
1513-In addition to ``extra_context``, the template's context will be:
1514-
1515-* ``week``: A ``datetime.date`` object representing the first day of the
1516-  given week.
1517-
1518-* ``object_list``: A list of objects available for the given week. This
1519-  variable's name depends on the ``template_object_name`` parameter, which
1520-  is ``'object'`` by default. If ``template_object_name`` is ``'foo'``,
1521-  this variable's name will be ``foo_list``.
1522-
1523-``django.views.generic.date_based.archive_day``
1524------------------------------------------------
1525-
1526-**Description:**
1527-
1528-A day archive page showing all objects in a given day. Days in the future throw
1529-a 404 error, regardless of whether any objects exist for future days, unless
1530-you set ``allow_future`` to ``True``.
1531-
1532-**Required arguments:**
1533-
1534-* ``year``: The four-digit year for which the archive serves (a string).
1535-
1536-* ``month``: The month for which the archive serves, formatted according to
1537-  the ``month_format`` argument.
1538-
1539-* ``day``: The day for which the archive serves, formatted according to the
1540-  ``day_format`` argument.
1541-
1542-* ``queryset``: A ``QuerySet`` of objects for which the archive serves.
1543-
1544-* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
1545-  the ``QuerySet``'s model that the date-based archive should use to
1546-  determine the objects on the page.
1547-
1548-**Optional arguments:**
1549-
1550-* ``month_format``: A format string that regulates what format the ``month``
1551-  parameter uses. This should be in the syntax accepted by Python's
1552-  :func:`~time.strftime`. It's set to ``"%b"`` by default, which is a
1553-  three-letter month abbreviation. To change it to use numbers, use
1554-  ``"%m"``.
1555-
1556-* ``day_format``: Like ``month_format``, but for the ``day`` parameter.
1557-  It defaults to ``"%d"`` (day of the month as a decimal number, 01-31).
1558-
1559-* ``template_name``: The full name of a template to use in rendering the
1560-  page. This lets you override the default template name (see below).
1561-
1562-* ``template_loader``: The template loader to use when loading the
1563-  template. By default, it's ``django.template.loader``.
1564-
1565-* ``extra_context``: A dictionary of values to add to the template
1566-  context. By default, this is an empty dictionary. If a value in the
1567-  dictionary is callable, the generic view will call it
1568-  just before rendering the template.
1569-
1570-* ``allow_empty``: A boolean specifying whether to display the page if no
1571-  objects are available. If this is ``False`` and no objects are available,
1572-  the view will raise a 404 instead of displaying an empty page. By
1573-  default, this is ``False``.
1574-
1575-* ``context_processors``: A list of template-context processors to apply to
1576-  the view's template.
1577-
1578-* ``template_object_name``:  Designates the name of the template variable
1579-  to use in the template context. By default, this is ``'object'``. The
1580-  view will append ``'_list'`` to the value of this parameter in
1581-  determining the variable's name.
1582-
1583-* ``mimetype``: The MIME type to use for the resulting document. Defaults
1584-  to the value of the :setting:`DEFAULT_CONTENT_TYPE` setting.
1585-
1586-* ``allow_future``: A boolean specifying whether to include "future"
1587-  objects on this page, where "future" means objects in which the field
1588-  specified in ``date_field`` is greater than the current date/time. By
1589-  default, this is ``False``.
1590-
1591-**Template name:**
1592-
1593-If ``template_name`` isn't specified, this view will use the template
1594-``<app_label>/<model_name>_archive_day.html`` by default.
1595-
1596-**Template context:**
1597-
1598-In addition to ``extra_context``, the template's context will be:
1599-
1600-* ``day``: A ``datetime.date`` object representing the given day.
1601-
1602-* ``next_day``: A ``datetime.date`` object representing the next day. If
1603-  the next day is in the future, this will be ``None``.
1604-
1605-* ``previous_day``: A ``datetime.date`` object representing the previous day.
1606-  Unlike ``next_day``, this will never be ``None``.
1607-
1608-* ``object_list``: A list of objects available for the given day. This
1609-  variable's name depends on the ``template_object_name`` parameter, which
1610-  is ``'object'`` by default. If ``template_object_name`` is ``'foo'``,
1611-  this variable's name will be ``foo_list``.
1612-
1613-``django.views.generic.date_based.archive_today``
1614--------------------------------------------------
1615-
1616-**Description:**
1617-
1618-A day archive page showing all objects for *today*. This is exactly the same as
1619-``archive_day``, except the ``year``/``month``/``day`` arguments are not used,
1620-and today's date is used instead.
1621-
1622-``django.views.generic.date_based.object_detail``
1623--------------------------------------------------
1624-
1625-**Description:**
1626-
1627-A page representing an individual object. If the object has a date value in the
1628-future, the view will throw a 404 error by default, unless you set
1629-``allow_future`` to ``True``.
1630-
1631-**Required arguments:**
1632-
1633-* ``year``: The object's four-digit year (a string).
1634-
1635-* ``month``: The object's month , formatted according to the
1636-  ``month_format`` argument.
1637-
1638-* ``day``: The object's day , formatted according to the ``day_format``
1639-  argument.
1640-
1641-* ``queryset``: A ``QuerySet`` that contains the object.
1642-
1643-* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in
1644-  the ``QuerySet``'s model that the generic view should use to look up the
1645-  object according to ``year``, ``month`` and ``day``.
1646-
1647-* Either ``object_id`` or (``slug`` *and* ``slug_field``) is required.
1648-
1649-  If you provide ``object_id``, it should be the value of the primary-key
1650-  field for the object being displayed on this page.
1651-
1652-  Otherwise, ``slug`` should be the slug of the given object, and
1653-  ``slug_field`` should be the name of the slug field in the ``QuerySet``'s
1654-  model. By default, ``slug_field`` is ``'slug'``.
1655-
1656-**Optional arguments:**
1657-
1658-* ``month_format``: A format string that regulates what format the ``month``
1659-  parameter uses. This should be in the syntax accepted by Python's
1660-  :func:`~time.strftime`. It's set to ``"%b"`` by default, which is a
1661-  three-letter month abbreviation. To change it to use numbers, use
1662-  ``"%m"``.
1663-
1664-* ``day_format``: Like ``month_format``, but for the ``day`` parameter.
1665-  It defaults to ``"%d"`` (day of the month as a decimal number, 01-31).
1666-
1667-* ``template_name``: The full name of a template to use in rendering the
1668-  page. This lets you override the default template name (see below).
1669-
1670-* ``template_name_field``: The name of a field on the object whose value is
1671-  the template name to use. This lets you store template names in the data.
1672-  In other words, if your object has a field ``'the_template'`` that
1673-  contains a string ``'foo.html'``, and you set ``template_name_field`` to
1674-  ``'the_template'``, then the generic view for this object will use the
1675-  template ``'foo.html'``.
1676-
1677-  It's a bit of a brain-bender, but it's useful in some cases.
1678-
1679-* ``template_loader``: The template loader to use when loading the
1680-  template. By default, it's ``django.template.loader``.
1681-
1682-* ``extra_context``: A dictionary of values to add to the template
1683-  context. By default, this is an empty dictionary. If a value in the
1684-  dictionary is callable, the generic view will call it
1685-  just before rendering the template.
1686-
1687-* ``context_processors``: A list of template-context processors to apply to
1688-  the view's template.
1689-
1690-* ``template_object_name``:  Designates the name of the template variable
1691-  to use in the template context. By default, this is ``'object'``.
1692-
1693-* ``mimetype``: The MIME type to use for the resulting document. Defaults
1694-  to the value of the :setting:`DEFAULT_CONTENT_TYPE` setting.
1695-
1696-* ``allow_future``: A boolean specifying whether to include "future"
1697-  objects on this page, where "future" means objects in which the field
1698-  specified in ``date_field`` is greater than the current date/time. By
1699-  default, this is ``False``.
1700-
1701-**Template name:**
1702-
1703-If ``template_name`` isn't specified, this view will use the template
1704-``<app_label>/<model_name>_detail.html`` by default.
1705-
1706-**Template context:**
1707-
1708-In addition to ``extra_context``, the template's context will be:
1709-
1710-* ``object``: The object. This variable's name depends on the
1711-  ``template_object_name`` parameter, which is ``'object'`` by default. If
1712-  ``template_object_name`` is ``'foo'``, this variable's name will be
1713-  ``foo``.
1714-
1715-.. module:: django.views.generic.list_detail
1716-
1717-List/detail generic views
1718-=========================
1719-
1720-The list-detail generic-view framework (in the
1721-``django.views.generic.list_detail`` module) is similar to the date-based one,
1722-except the former simply has two views: a list of objects and an individual
1723-object page.
1724-
1725-``django.views.generic.list_detail.object_list``
1726-------------------------------------------------
1727-
1728-**Description:**
1729-
1730-A page representing a list of objects.
1731-
1732-**Required arguments:**
1733-
1734-* ``queryset``: A ``QuerySet`` that represents the objects.
1735-
1736-**Optional arguments:**
1737-
1738-* ``paginate_by``: An integer specifying how many objects should be
1739-  displayed per page. If this is given, the view will paginate objects with
1740-  ``paginate_by`` objects per page. The view will expect either a ``page``
1741-  query string parameter (via ``GET``) or a ``page`` variable specified in
1742-  the URLconf. See `Notes on pagination`_ below.
1743-
1744-* ``page``: The current page number, as an integer, or the string
1745-  ``'last'``. This is 1-based. See `Notes on pagination`_ below.
1746-
1747-* ``template_name``: The full name of a template to use in rendering the
1748-  page. This lets you override the default template name (see below).
1749-
1750-* ``template_loader``: The template loader to use when loading the
1751-  template. By default, it's ``django.template.loader``.
1752-
1753-* ``extra_context``: A dictionary of values to add to the template
1754-  context. By default, this is an empty dictionary. If a value in the
1755-  dictionary is callable, the generic view will call it
1756-  just before rendering the template.
1757-
1758-* ``allow_empty``: A boolean specifying whether to display the page if no
1759-  objects are available. If this is ``False`` and no objects are available,
1760-  the view will raise a 404 instead of displaying an empty page. By
1761-  default, this is ``True``.
1762-
1763-* ``context_processors``: A list of template-context processors to apply to
1764-  the view's template.
1765-
1766-* ``template_object_name``:  Designates the name of the template variable
1767-  to use in the template context. By default, this is ``'object'``. The
1768-  view will append ``'_list'`` to the value of this parameter in
1769-  determining the variable's name.
1770-
1771-* ``mimetype``: The MIME type to use for the resulting document. Defaults
1772-  to the value of the :setting:`DEFAULT_CONTENT_TYPE` setting.
1773-
1774-**Template name:**
1775-
1776-If ``template_name`` isn't specified, this view will use the template
1777-``<app_label>/<model_name>_list.html`` by default.
1778-
1779-**Template context:**
1780-
1781-In addition to ``extra_context``, the template's context will be:
1782-
1783-* ``object_list``: The list of objects. This variable's name depends on the
1784-  ``template_object_name`` parameter, which is ``'object'`` by default. If
1785-  ``template_object_name`` is ``'foo'``, this variable's name will be
1786-  ``foo_list``.
1787-
1788-* ``is_paginated``: A boolean representing whether the results are
1789-  paginated. Specifically, this is set to ``False`` if the number of
1790-  available objects is less than or equal to ``paginate_by``.
1791-
1792-If the results are paginated, the context will contain these extra variables:
1793-
1794-* ``paginator``: An instance of ``django.core.paginator.Paginator``.
1795-
1796-* ``page_obj``: An instance of ``django.core.paginator.Page``.
1797-
1798-Notes on pagination
1799-~~~~~~~~~~~~~~~~~~~
1800-
1801-If ``paginate_by`` is specified, Django will paginate the results. You can
1802-specify the page number in the URL in one of two ways:
1803-
1804-* Use the ``page`` parameter in the URLconf. For example, this is what
1805-  your URLconf might look like::
1806-
1807-    (r'^objects/page(?P<page>[0-9]+)/$', 'object_list', dict(info_dict))
1808-
1809-* Pass the page number via the ``page`` query-string parameter. For
1810-  example, a URL would look like this::
1811-
1812-    /objects/?page=3
1813-
1814-* To loop over all the available page numbers, use the ``page_range``
1815-  variable. You can iterate over the list provided by ``page_range``
1816-  to create a link to every page of results.
1817-
1818-These values and lists are 1-based, not 0-based, so the first page would be
1819-represented as page ``1``.
1820-
1821-For more on pagination, read the :doc:`pagination documentation
1822-</topics/pagination>`.
1823-
1824-As a special case, you are also permitted to use ``last`` as a value for
1825-``page``::
1826-
1827-    /objects/?page=last
1828-
1829-This allows you to access the final page of results without first having to
1830-determine how many pages there are.
1831-
1832-Note that ``page`` *must* be either a valid page number or the value ``last``;
1833-any other value for ``page`` will result in a 404 error.
1834-
1835-``django.views.generic.list_detail.object_detail``
1836---------------------------------------------------
1837-
1838-A page representing an individual object.
1839-
1840-**Description:**
1841-
1842-A page representing an individual object.
1843-
1844-**Required arguments:**
1845-
1846-* ``queryset``: A ``QuerySet`` that contains the object.
1847-
1848-* Either ``object_id`` or (``slug`` *and* ``slug_field``) is required.
1849-
1850-  If you provide ``object_id``, it should be the value of the primary-key
1851-  field for the object being displayed on this page.
1852-
1853-  Otherwise, ``slug`` should be the slug of the given object, and
1854-  ``slug_field`` should be the name of the slug field in the ``QuerySet``'s
1855-  model. By default, ``slug_field`` is ``'slug'``.
1856-
1857-**Optional arguments:**
1858-
1859-* ``template_name``: The full name of a template to use in rendering the
1860-  page. This lets you override the default template name (see below).
1861-
1862-* ``template_name_field``: The name of a field on the object whose value is
1863-  the template name to use. This lets you store template names in the data.
1864-  In other words, if your object has a field ``'the_template'`` that
1865-  contains a string ``'foo.html'``, and you set ``template_name_field`` to
1866-  ``'the_template'``, then the generic view for this object will use the
1867-  template ``'foo.html'``.
1868-
1869-  It's a bit of a brain-bender, but it's useful in some cases.
1870-
1871-* ``template_loader``: The template loader to use when loading the
1872-  template. By default, it's ``django.template.loader``.
1873-
1874-* ``extra_context``: A dictionary of values to add to the template
1875-  context. By default, this is an empty dictionary. If a value in the
1876-  dictionary is callable, the generic view will call it
1877-  just before rendering the template.
1878-
1879-* ``context_processors``: A list of template-context processors to apply to
1880-  the view's template.
1881-
1882-* ``template_object_name``:  Designates the name of the template variable
1883-  to use in the template context. By default, this is ``'object'``.
1884-
1885-* ``mimetype``: The MIME type to use for the resulting document. Defaults
1886-  to the value of the :setting:`DEFAULT_CONTENT_TYPE` setting.
1887-
1888-**Template name:**
1889-
1890-If ``template_name`` isn't specified, this view will use the template
1891-``<app_label>/<model_name>_detail.html`` by default.
1892-
1893-**Template context:**
1894-
1895-In addition to ``extra_context``, the template's context will be:
1896-
1897-* ``object``: The object. This variable's name depends on the
1898-  ``template_object_name`` parameter, which is ``'object'`` by default. If
1899-  ``template_object_name`` is ``'foo'``, this variable's name will be
1900-  ``foo``.
1901-
1902-.. module:: django.views.generic.create_update
1903-
1904-Create/update/delete generic views
1905-==================================
1906-
1907-The ``django.views.generic.create_update`` module contains a set of functions
1908-for creating, editing and deleting objects.
1909-
1910-``django.views.generic.create_update.create_object``
1911-----------------------------------------------------
1912-
1913-**Description:**
1914-
1915-A page that displays a form for creating an object, redisplaying the form with
1916-validation errors (if there are any) and saving the object.
1917-
1918-**Required arguments:**
1919-
1920-* Either ``form_class`` or ``model`` is required.
1921-
1922-  If you provide ``form_class``, it should be a ``django.forms.ModelForm``
1923-  subclass. Use this argument when you need to customize the model's form.
1924-  See the :doc:`ModelForm docs </topics/forms/modelforms>` for more
1925-  information.
1926-
1927-  Otherwise, ``model`` should be a Django model class and the form used
1928-  will be a standard ``ModelForm`` for ``model``.
1929-
1930-**Optional arguments:**
1931-
1932-* ``post_save_redirect``: A URL to which the view will redirect after
1933-  saving the object. By default, it's ``object.get_absolute_url()``.
1934-
1935-  ``post_save_redirect`` may contain dictionary string formatting, which
1936-  will be interpolated against the object's field attributes. For example,
1937-  you could use ``post_save_redirect="/polls/%(slug)s/"``.
1938-
1939-* ``login_required``: A boolean that designates whether a user must be
1940-  logged in, in order to see the page and save changes. This hooks into the
1941-  Django :doc:`authentication system </topics/auth>`. By default, this is
1942-  ``False``.
1943-
1944-  If this is ``True``, and a non-logged-in user attempts to visit this page
1945-  or save the form, Django will redirect the request to ``/accounts/login/``.
1946-
1947-* ``template_name``: The full name of a template to use in rendering the
1948-  page. This lets you override the default template name (see below).
1949-
1950-* ``template_loader``: The template loader to use when loading the
1951-  template. By default, it's ``django.template.loader``.
1952-
1953-* ``extra_context``: A dictionary of values to add to the template
1954-  context. By default, this is an empty dictionary. If a value in the
1955-  dictionary is callable, the generic view will call it
1956-  just before rendering the template.
1957-
1958-* ``context_processors``: A list of template-context processors to apply to
1959-  the view's template.
1960-
1961-**Template name:**
1962-
1963-If ``template_name`` isn't specified, this view will use the template
1964-``<app_label>/<model_name>_form.html`` by default.
1965-
1966-**Template context:**
1967-
1968-In addition to ``extra_context``, the template's context will be:
1969-
1970-* ``form``: A ``django.forms.ModelForm`` instance representing the form
1971-  for creating the object. This lets you refer to form fields easily in the
1972-  template system.
1973-
1974-  For example, if the model has two fields, ``name`` and ``address``::
1975-
1976-      <form action="" method="post">
1977-      <p>{{ form.name.label_tag }} {{ form.name }}</p>
1978-      <p>{{ form.address.label_tag }} {{ form.address }}</p>
1979-      </form>
1980-
1981-  See the :doc:`forms documentation </topics/forms/index>` for more
1982-  information about using ``Form`` objects in templates.
1983-
1984-``django.views.generic.create_update.update_object``
1985-----------------------------------------------------
1986-
1987-**Description:**
1988-
1989-A page that displays a form for editing an existing object, redisplaying the
1990-form with validation errors (if there are any) and saving changes to the
1991-object. This uses a form automatically generated from the object's
1992-model class.
1993-
1994-**Required arguments:**
1995-
1996-* Either ``form_class`` or ``model`` is required.
1997-
1998-  If you provide ``form_class``, it should be a ``django.forms.ModelForm``
1999-  subclass. Use this argument when you need to customize the model's form.
2000-  See the :doc:`ModelForm docs </topics/forms/modelforms>` for more
2001-  information.
2002-
2003-  Otherwise, ``model`` should be a Django model class and the form used
2004-  will be a standard ``ModelForm`` for ``model``.
2005-
2006-* Either ``object_id`` or (``slug`` *and* ``slug_field``) is required.
2007-
2008-  If you provide ``object_id``, it should be the value of the primary-key
2009-  field for the object being displayed on this page.
2010-
2011-  Otherwise, ``slug`` should be the slug of the given object, and
2012-  ``slug_field`` should be the name of the slug field in the ``QuerySet``'s
2013-  model. By default, ``slug_field`` is ``'slug'``.
2014-
2015-**Optional arguments:**
2016-
2017-* ``post_save_redirect``: A URL to which the view will redirect after
2018-  saving the object. By default, it's ``object.get_absolute_url()``.
2019-
2020-  ``post_save_redirect`` may contain dictionary string formatting, which
2021-  will be interpolated against the object's field attributes. For example,
2022-  you could use ``post_save_redirect="/polls/%(slug)s/"``.
2023-
2024-* ``login_required``: A boolean that designates whether a user must be
2025-  logged in, in order to see the page and save changes. This hooks into the
2026-  Django :doc:`authentication system </topics/auth>`. By default, this is
2027-  ``False``.
2028-
2029-  If this is ``True``, and a non-logged-in user attempts to visit this page
2030-  or save the form, Django will redirect to :setting:`LOGIN_URL` (which
2031-  defaults to ``/accounts/login/``).
2032-
2033-* ``template_name``: The full name of a template to use in rendering the
2034-  page. This lets you override the default template name (see below).
2035-
2036-* ``template_loader``: The template loader to use when loading the
2037-  template. By default, it's ``django.template.loader``.
2038-
2039-* ``extra_context``: A dictionary of values to add to the template
2040-  context. By default, this is an empty dictionary. If a value in the
2041-  dictionary is callable, the generic view will call it
2042-  just before rendering the template.
2043-
2044-* ``context_processors``: A list of template-context processors to apply to
2045-  the view's template.
2046-
2047-* ``template_object_name``:  Designates the name of the template variable
2048-  to use in the template context. By default, this is ``'object'``.
2049-
2050-**Template name:**
2051-
2052-If ``template_name`` isn't specified, this view will use the template
2053-``<app_label>/<model_name>_form.html`` by default.
2054-
2055-**Template context:**
2056-
2057-In addition to ``extra_context``, the template's context will be:
2058-
2059-* ``form``: A ``django.forms.ModelForm`` instance representing the form
2060-  for editing the object. This lets you refer to form fields easily in the
2061-  template system.
2062-
2063-  For example, if the model has two fields, ``name`` and ``address``::
2064-
2065-      <form action="" method="post">
2066-      <p>{{ form.name.label_tag }} {{ form.name }}</p>
2067-      <p>{{ form.address.label_tag }} {{ form.address }}</p>
2068-      </form>
2069-
2070-  See the :doc:`forms documentation </topics/forms/index>` for more
2071-  information about using ``Form`` objects in templates.
2072-
2073-* ``object``: The original object being edited. This variable's name
2074-  depends on the ``template_object_name`` parameter, which is ``'object'``
2075-  by default. If ``template_object_name`` is ``'foo'``, this variable's
2076-  name will be ``foo``.
2077-
2078-``django.views.generic.create_update.delete_object``
2079-----------------------------------------------------
2080-
2081-**Description:**
2082-
2083-A view that displays a confirmation page and deletes an existing object. The
2084-given object will only be deleted if the request method is ``POST``. If this
2085-view is fetched via ``GET``, it will display a confirmation page that should
2086-contain a form that POSTs to the same URL.
2087-
2088-**Required arguments:**
2089-
2090-* ``model``: The Django model class of the object that the form will
2091-  delete.
2092-
2093-* Either ``object_id`` or (``slug`` *and* ``slug_field``) is required.
2094-
2095-  If you provide ``object_id``, it should be the value of the primary-key
2096-  field for the object being displayed on this page.
2097-
2098-  Otherwise, ``slug`` should be the slug of the given object, and
2099-  ``slug_field`` should be the name of the slug field in the ``QuerySet``'s
2100-  model. By default, ``slug_field`` is ``'slug'``.
2101-
2102-* ``post_delete_redirect``: A URL to which the view will redirect after
2103-  deleting the object.
2104-
2105-**Optional arguments:**
2106-
2107-* ``login_required``: A boolean that designates whether a user must be
2108-  logged in, in order to see the page and save changes. This hooks into the
2109-  Django :doc:`authentication system </topics/auth>`. By default, this is
2110-  ``False``.
2111-
2112-  If this is ``True``, and a non-logged-in user attempts to visit this page
2113-  or save the form, Django will redirect to :setting:`LOGIN_URL` (which
2114-  defaults to ``/accounts/login/``).
2115-
2116-* ``template_name``: The full name of a template to use in rendering the
2117-  page. This lets you override the default template name (see below).
2118-
2119-* ``template_loader``: The template loader to use when loading the
2120-  template. By default, it's ``django.template.loader``.
2121-
2122-* ``extra_context``: A dictionary of values to add to the template
2123-  context. By default, this is an empty dictionary. If a value in the
2124-  dictionary is callable, the generic view will call it
2125-  just before rendering the template.
2126-
2127-* ``context_processors``: A list of template-context processors to apply to
2128-  the view's template.
2129-
2130-* ``template_object_name``:  Designates the name of the template variable
2131-  to use in the template context. By default, this is ``'object'``.
2132-
2133-**Template name:**
2134-
2135-If ``template_name`` isn't specified, this view will use the template
2136-``<app_label>/<model_name>_confirm_delete.html`` by default.
2137-
2138-**Template context:**
2139-
2140-In addition to ``extra_context``, the template's context will be:
2141-
2142-* ``object``: The original object that's about to be deleted. This
2143-  variable's name depends on the ``template_object_name`` parameter, which
2144-  is ``'object'`` by default. If ``template_object_name`` is ``'foo'``,
2145-  this variable's name will be ``foo``.
2146diff --git a/docs/ref/index.txt b/docs/ref/index.txt
2147index db09afe..32b2631 100644
2148--- a/docs/ref/index.txt
2149+++ b/docs/ref/index.txt
2150@@ -24,11 +24,3 @@ API Reference
2151    unicode
2152    utils
2153    validators
2154-
2155-Deprecated features
2156--------------------
2157-
2158-.. toctree::
2159-   :maxdepth: 1
2160-
2161-   generic-views
2162diff --git a/docs/releases/1.1-alpha-1.txt b/docs/releases/1.1-alpha-1.txt
2163index b123a06..10b0d5d 100644
2164--- a/docs/releases/1.1-alpha-1.txt
2165+++ b/docs/releases/1.1-alpha-1.txt
2166@@ -88,8 +88,8 @@ Other new features and changes introduced since Django 1.0 include:
2167   which return the list of hidden -- i.e., ``<input type="hidden">`` -- and
2168   visible fields on the form, respectively.
2169 
2170-* The ``redirect_to`` generic view (see :doc:`the generic views documentation
2171-  </ref/generic-views>`) now accepts an additional keyword argument
2172+* The ``redirect_to`` generic view
2173+  now accepts an additional keyword argument
2174   ``permanent``. If ``permanent`` is ``True``, the view will emit an HTTP
2175   permanent redirect (status code 301). If ``False``, the view will emit an HTTP
2176   temporary redirect (status code 302).
2177diff --git a/docs/releases/1.1.txt b/docs/releases/1.1.txt
2178index 15e9c84..1294011 100644
2179--- a/docs/releases/1.1.txt
2180+++ b/docs/releases/1.1.txt
2181@@ -396,8 +396,8 @@ Other new features and changes introduced since Django 1.0 include:
2182   which return the list of hidden -- i.e., ``<input type="hidden">`` -- and
2183   visible fields on the form, respectively.
2184 
2185-* The ``redirect_to`` generic view (see :doc:`the generic views documentation
2186-  </ref/generic-views>`) now accepts an additional keyword argument
2187+* The ``redirect_to`` generic view
2188+  now accepts an additional keyword argument
2189   ``permanent``. If ``permanent`` is ``True``, the view will emit an HTTP
2190   permanent redirect (status code 301). If ``False``, the view will emit an HTTP
2191   temporary redirect (status code 302).
2192diff --git a/docs/releases/1.3-alpha-1.txt b/docs/releases/1.3-alpha-1.txt
2193index f1ff23b..4e6c72a 100644
2194--- a/docs/releases/1.3-alpha-1.txt
2195+++ b/docs/releases/1.3-alpha-1.txt
2196@@ -41,7 +41,7 @@ the basis for reusable applications that can be easily extended.
2197 See :doc:`the documentation on Class-based Generic Views
2198 </topics/class-based-views>` for more details. There is also a document to
2199 help you :doc:`convert your function-based generic views to class-based
2200-views</topics/generic-views-migration>`.
2201+views <https://docs.djangoproject.com/en/1.4/topics/generic-views-migration/>`_.
2202 
2203 Logging
2204 ~~~~~~~
2205diff --git a/docs/releases/1.3.txt b/docs/releases/1.3.txt
2206index 224cd47..3548a00 100644
2207--- a/docs/releases/1.3.txt
2208+++ b/docs/releases/1.3.txt
2209@@ -81,9 +81,9 @@ used as the basis for reusable applications that can be easily
2210 extended.
2211 
2212 See :doc:`the documentation on class-based generic views</topics/class-based-views>`
2213-for more details. There is also a document to help you :doc:`convert
2214+for more details. There is also a document to help you `convert
2215 your function-based generic views to class-based
2216-views</topics/generic-views-migration>`.
2217+views <https://docs.djangoproject.com/en/1.4/topics/generic-views-migration/>`_.
2218 
2219 Logging
2220 ~~~~~~~
2221diff --git a/docs/topics/auth.txt b/docs/topics/auth.txt
2222index d266b92..b3ed834 100644
2223--- a/docs/topics/auth.txt
2224+++ b/docs/topics/auth.txt
2225@@ -1472,19 +1472,6 @@ To limit access to a :doc:`class-based generic view </ref/class-based-views>`,
2226 decorate the :meth:`View.dispatch <django.views.generic.base.View.dispatch>`
2227 method on the class. See :ref:`decorating-class-based-views` for details.
2228 
2229-Function-based generic views
2230-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2231-
2232-To limit access to a :doc:`function-based generic view </ref/generic-views>`,
2233-write a thin wrapper around the view, and point your URLconf to your wrapper
2234-instead of the generic view itself. For example::
2235-
2236-    from django.views.generic.date_based import object_detail
2237-
2238-    @login_required
2239-    def limited_object_detail(*args, **kwargs):
2240-        return object_detail(*args, **kwargs)
2241-
2242 .. _permissions:
2243 
2244 Permissions
2245diff --git a/docs/topics/class-based-views.txt b/docs/topics/class-based-views.txt
2246index e1e2618..6df8f78 100644
2247--- a/docs/topics/class-based-views.txt
2248+++ b/docs/topics/class-based-views.txt
2249@@ -6,13 +6,9 @@ Class-based generic views
2250 
2251 .. note::
2252     Prior to Django 1.3, generic views were implemented as functions. The
2253-    function-based implementation has been deprecated in favor of the
2254+    function-based implementation has been removed in favor of the
2255     class-based approach described here.
2256 
2257-    For details on the previous generic views implementation,
2258-    see the :doc:`topic guide </topics/generic-views>` and
2259-    :doc:`detailed reference </ref/generic-views>`.
2260-
2261 Writing Web applications can be monotonous, because we repeat certain patterns
2262 again and again. Django tries to take away some of that monotony at the model
2263 and template layers, but Web developers also experience this boredom at the view
2264diff --git a/docs/topics/generic-views-migration.txt b/docs/topics/generic-views-migration.txt
2265deleted file mode 100644
2266index 0647336..0000000
2267--- a/docs/topics/generic-views-migration.txt
2268+++ /dev/null
2269@@ -1,159 +0,0 @@
2270-======================================
2271-Migrating function-based generic views
2272-======================================
2273-
2274-All the :doc:`function-based generic views</ref/generic-views>`
2275-that existed in Django 1.2 have analogs as :doc:`class-based generic
2276-views</ref/class-based-views>` in Django 1.3. The feature set
2277-exposed in those function-based views can be replicated in a
2278-class-based way.
2279-
2280-How to migrate
2281-==============
2282-
2283-Replace generic views with generic classes
2284-------------------------------------------
2285-
2286-Existing usage of function-based generic views should be replaced with
2287-their class-based analogs:
2288-
2289-====================================================  ====================================================
2290-Old function-based generic view                       New class-based generic view
2291-====================================================  ====================================================
2292-``django.views.generic.simple.direct_to_template``    :class:`django.views.generic.base.TemplateView`
2293-``django.views.generic.simple.redirect_to``           :class:`django.views.generic.base.RedirectView`
2294-``django.views.generic.list_detail.object_list``      :class:`django.views.generic.list.ListView`
2295-``django.views.generic.list_detail.object_detail``    :class:`django.views.generic.detail.DetailView`
2296-``django.views.generic.create_update.create_object``  :class:`django.views.generic.edit.CreateView`
2297-``django.views.generic.create_update.update_object``  :class:`django.views.generic.edit.UpdateView`
2298-``django.views.generic.create_update.delete_object``  :class:`django.views.generic.edit.DeleteView`
2299-``django.views.generic.date_based.archive_index``     :class:`django.views.generic.dates.ArchiveIndexView`
2300-``django.views.generic.date_based.archive_year``      :class:`django.views.generic.dates.YearArchiveView`
2301-``django.views.generic.date_based.archive_month``     :class:`django.views.generic.dates.MonthArchiveView`
2302-``django.views.generic.date_based.archive_week``      :class:`django.views.generic.dates.WeekArchiveView`
2303-``django.views.generic.date_based.archive_day``       :class:`django.views.generic.dates.DayArchiveView`
2304-``django.views.generic.date_based.archive_today``     :class:`django.views.generic.dates.TodayArchiveView`
2305-``django.views.generic.date_based.object_detail``     :class:`django.views.generic.dates.DateDetailView`
2306-====================================================  ====================================================
2307-
2308-To do this, replace the reference to the generic view function with
2309-a ``as_view()`` instantiation of the class-based view. For example,
2310-the old-style ``direct_to_template`` pattern::
2311-
2312-    ('^about/$', direct_to_template, {'template': 'about.html'})
2313-
2314-can be replaced with an instance of
2315-:class:`~django.views.generic.base.TemplateView`::
2316-
2317-    ('^about/$', TemplateView.as_view(template_name='about.html'))
2318-
2319-``template`` argument to ``direct_to_template`` views
2320------------------------------------------------------
2321-
2322-The ``template`` argument to the ``direct_to_template`` view has been renamed
2323-``template_name``. This has been done to maintain consistency with other views.
2324-
2325-``object_id`` argument to detail views
2326---------------------------------------
2327-
2328-The object_id argument to the ``object_detail`` view has been renamed
2329-``pk`` on the :class:`~django.views.generic.detail.DetailView`.
2330-
2331-``template_object_name``
2332-------------------------
2333-
2334-``template_object_name`` has been renamed ``context_object_name``,
2335-reflecting the fact that the context data can be used for purposes
2336-other than template rendering (e.g., to populate JSON output).
2337-
2338-The ``_list`` suffix on list views
2339-----------------------------------
2340-
2341-In a function-based :class:`ListView`, the ``template_object_name``
2342-was appended with the suffix ``'_list'`` to yield the final context
2343-variable name. In a class-based ``ListView``, the
2344-``context_object_name`` is used verbatim. The ``'_list'`` suffix
2345-is only applied when generating a default context object name.
2346-
2347-The context data for ``object_list`` views
2348-------------------------------------------
2349-
2350-The context provided by :class:`~django.views.generic.list.MultipleObjectMixin`
2351-is quite different from that provided by ``object_list``, with most pagination
2352-related variables replaced by a single ``page_obj`` object. The following are no
2353-longer provided:
2354-
2355-* ``first_on_page``
2356-* ``has_next``
2357-* ``has_previous``
2358-* ``hits``
2359-* ``last_on_page``
2360-* ``next``
2361-* ``page_range``
2362-* ``page``
2363-* ``pages``
2364-* ``previous``
2365-* ``results_per_page``
2366-
2367-``extra_context``
2368------------------
2369-
2370-Function-based generic views provided an ``extra_context`` argument
2371-as way to insert extra items into the context at time of rendering.
2372-
2373-Class-based views don't provide an ``extra_context`` argument.
2374-Instead, you subclass the view, overriding :meth:`get_context_data()`.
2375-For example::
2376-
2377-    class MyListView(ListView):
2378-        def get_context_data(self, **kwargs):
2379-            context = super(MyListView, self).get_context_data(**kwargs)
2380-            context.update({
2381-                'foo': 42,
2382-                'bar': 37
2383-            })
2384-            return context
2385-
2386-``post_save_redirect`` argument to create and update views
2387-----------------------------------------------------------
2388-
2389-The ``post_save_redirect`` argument to the create and update views
2390-has been renamed ``success_url`` on the
2391-:class:`~django.views.generic.edit.ModelFormMixin`.
2392-
2393-``mimetype``
2394-------------
2395-
2396-Some function-based generic views provided a ``mimetype`` argument
2397-as way to control the mimetype of the response.
2398-
2399-Class-based views don't provide a ``mimetype`` argument. Instead, you
2400-subclass the view, overriding
2401-:meth:`TemplateResponseMixin.render_to_response()` and pass in arguments for
2402-the TemplateResponse constructor. For example::
2403-
2404-    class MyListView(ListView):
2405-        def render_to_response(self, context, **kwargs):
2406-            return super(MyListView, self).render_to_response(context,
2407-                            content_type='application/json', **kwargs)
2408-
2409-``context_processors``
2410-----------------------
2411-
2412-Some function-based generic views provided a ``context_processors``
2413-argument that could be used to force the use of specialized context
2414-processors when rendering template content.
2415-
2416-Class-based views don't provide a ``context_processors`` argument.
2417-Instead, you subclass the view, overriding
2418-:meth:`TemplateResponseMixin.render_to_response()`, and passing in
2419-a context instance that has been instantiated with the processors
2420-you want to use. For example::
2421-
2422-    class MyListView(ListView):
2423-        def render_to_response(self, context, **kwargs):
2424-            return super(MyListView, self).render_to_response(
2425-                    RequestContext(self.request,
2426-                                   context,
2427-                                   processors=[custom_processor]),
2428-                    **kwargs)
2429diff --git a/docs/topics/generic-views.txt b/docs/topics/generic-views.txt
2430deleted file mode 100644
2431index 77232bc..0000000
2432--- a/docs/topics/generic-views.txt
2433+++ /dev/null
2434@@ -1,511 +0,0 @@
2435-=============
2436-Generic views
2437-=============
2438-
2439-
2440-.. versionchanged:: 1.3
2441-
2442-.. note::
2443-
2444-    From Django 1.3, function-based generic views have been deprecated in favor
2445-    of a class-based approach, described in the class-based views :doc:`topic
2446-    guide </topics/class-based-views>` and :doc:`detailed reference
2447-    </ref/class-based-views>`.
2448-
2449-Writing Web applications can be monotonous, because we repeat certain patterns
2450-again and again. Django tries to take away some of that monotony at the model
2451-and template layers, but Web developers also experience this boredom at the view
2452-level.
2453-
2454-Django's *generic views* were developed to ease that pain. They take certain
2455-common idioms and patterns found in view development and abstract them so that
2456-you can quickly write common views of data without having to write too much
2457-code.
2458-
2459-We can recognize certain common tasks, like displaying a list of objects, and
2460-write code that displays a list of *any* object. Then the model in question can
2461-be passed as an extra argument to the URLconf.
2462-
2463-Django ships with generic views to do the following:
2464-
2465-* Perform common "simple" tasks: redirect to a different page and
2466-  render a given template.
2467-
2468-* Display list and detail pages for a single object. If we were creating an
2469-  application to manage conferences then a ``talk_list`` view and a
2470-  ``registered_user_list`` view would be examples of list views. A single
2471-  talk page is an example of what we call a "detail" view.
2472-
2473-* Present date-based objects in year/month/day archive pages,
2474-  associated detail, and "latest" pages. The Django Weblog's
2475-  (https://www.djangoproject.com/weblog/) year, month, and
2476-  day archives are built with these, as would be a typical
2477-  newspaper's archives.
2478-
2479-* Allow users to create, update, and delete objects -- with or
2480-  without authorization.
2481-
2482-Taken together, these views provide easy interfaces to perform the most common
2483-tasks developers encounter.
2484-
2485-Using generic views
2486-===================
2487-
2488-All of these views are used by creating configuration dictionaries in
2489-your URLconf files and passing those dictionaries as the third member of the
2490-URLconf tuple for a given pattern.
2491-
2492-For example, here's a simple URLconf you could use to present a static "about"
2493-page::
2494-
2495-    from django.conf.urls import patterns, url, include
2496-    from django.views.generic.simple import direct_to_template
2497-
2498-    urlpatterns = patterns('',
2499-        ('^about/$', direct_to_template, {
2500-            'template': 'about.html'
2501-        })
2502-    )
2503-
2504-Though this might seem a bit "magical" at first glance  -- look, a view with no
2505-code! --, actually the ``direct_to_template`` view simply grabs information from
2506-the extra-parameters dictionary and uses that information when rendering the
2507-view.
2508-
2509-Because this generic view -- and all the others -- is a regular view function
2510-like any other, we can reuse it inside our own views. As an example, let's
2511-extend our "about" example to map URLs of the form ``/about/<whatever>/`` to
2512-statically rendered ``about/<whatever>.html``. We'll do this by first modifying
2513-the URLconf to point to a view function:
2514-
2515-.. parsed-literal::
2516-
2517-    from django.conf.urls import patterns, url, include
2518-    from django.views.generic.simple import direct_to_template
2519-    **from books.views import about_pages**
2520-
2521-    urlpatterns = patterns('',
2522-        ('^about/$', direct_to_template, {
2523-            'template': 'about.html'
2524-        }),
2525-        **('^about/(\\w+)/$', about_pages),**
2526-    )
2527-
2528-Next, we'll write the ``about_pages`` view::
2529-
2530-    from django.http import Http404
2531-    from django.template import TemplateDoesNotExist
2532-    from django.views.generic.simple import direct_to_template
2533-
2534-    def about_pages(request, page):
2535-        try:
2536-            return direct_to_template(request, template="about/%s.html" % page)
2537-        except TemplateDoesNotExist:
2538-            raise Http404()
2539-
2540-Here we're treating ``direct_to_template`` like any other function. Since it
2541-returns an ``HttpResponse``, we can simply return it as-is. The only slightly
2542-tricky business here is dealing with missing templates. We don't want a
2543-nonexistent template to cause a server error, so we catch
2544-``TemplateDoesNotExist`` exceptions and return 404 errors instead.
2545-
2546-.. admonition:: Is there a security vulnerability here?
2547-
2548-    Sharp-eyed readers may have noticed a possible security hole: we're
2549-    constructing the template name using interpolated content from the browser
2550-    (``template="about/%s.html" % page``). At first glance, this looks like a
2551-    classic *directory traversal* vulnerability. But is it really?
2552-
2553-    Not exactly. Yes, a maliciously crafted value of ``page`` could cause
2554-    directory traversal, but although ``page`` *is* taken from the request URL,
2555-    not every value will be accepted. The key is in the URLconf: we're using
2556-    the regular expression ``\w+`` to match the ``page`` part of the URL, and
2557-    ``\w`` only accepts letters and numbers. Thus, any malicious characters
2558-    (dots and slashes, here) will be rejected by the URL resolver before they
2559-    reach the view itself.
2560-
2561-Generic views of objects
2562-========================
2563-
2564-The ``direct_to_template`` certainly is useful, but Django's generic views
2565-really shine when it comes to presenting views on your database content. Because
2566-it's such a common task, Django comes with a handful of built-in generic views
2567-that make generating list and detail views of objects incredibly easy.
2568-
2569-Let's take a look at one of these generic views: the "object list" view. We'll
2570-be using these models::
2571-
2572-    # models.py
2573-    from django.db import models
2574-
2575-    class Publisher(models.Model):
2576-        name = models.CharField(max_length=30)
2577-        address = models.CharField(max_length=50)
2578-        city = models.CharField(max_length=60)
2579-        state_province = models.CharField(max_length=30)
2580-        country = models.CharField(max_length=50)
2581-        website = models.URLField()
2582-
2583-        def __unicode__(self):
2584-            return self.name
2585-
2586-        class Meta:
2587-            ordering = ["-name"]
2588-
2589-    class Book(models.Model):
2590-        title = models.CharField(max_length=100)
2591-        authors = models.ManyToManyField('Author')
2592-        publisher = models.ForeignKey(Publisher)
2593-        publication_date = models.DateField()
2594-
2595-To build a list page of all publishers, we'd use a URLconf along these lines::
2596-
2597-    from django.conf.urls import patterns, url, include
2598-    from django.views.generic import list_detail
2599-    from books.models import Publisher
2600-
2601-    publisher_info = {
2602-        "queryset" : Publisher.objects.all(),
2603-    }
2604-
2605-    urlpatterns = patterns('',
2606-        (r'^publishers/$', list_detail.object_list, publisher_info)
2607-    )
2608-
2609-That's all the Python code we need to write. We still need to write a template,
2610-however. We could explicitly tell the ``object_list`` view which template to use
2611-by including a ``template_name`` key in the extra arguments dictionary, but in
2612-the absence of an explicit template Django will infer one from the object's
2613-name. In this case, the inferred template will be
2614-``"books/publisher_list.html"`` -- the "books" part comes from the name of the
2615-app that defines the model, while the "publisher" bit is just the lowercased
2616-version of the model's name.
2617-
2618-.. highlightlang:: html+django
2619-
2620-This template will be rendered against a context containing a variable called
2621-``object_list`` that contains all the publisher objects. A very simple template
2622-might look like the following::
2623-
2624-    {% extends "base.html" %}
2625-
2626-    {% block content %}
2627-        <h2>Publishers</h2>
2628-        <ul>
2629-            {% for publisher in object_list %}
2630-                <li>{{ publisher.name }}</li>
2631-            {% endfor %}
2632-        </ul>
2633-    {% endblock %}
2634-
2635-That's really all there is to it. All the cool features of generic views come
2636-from changing the "info" dictionary passed to the generic view. The
2637-:doc:`generic views reference</ref/generic-views>` documents all the generic
2638-views and all their options in detail; the rest of this document will consider
2639-some of the common ways you might customize and extend generic views.
2640-
2641-Extending generic views
2642-=======================
2643-
2644-.. highlightlang:: python
2645-
2646-There's no question that using generic views can speed up development
2647-substantially. In most projects, however, there comes a moment when the
2648-generic views no longer suffice. Indeed, the most common question asked by new
2649-Django developers is how to make generic views handle a wider array of
2650-situations.
2651-
2652-Luckily, in nearly every one of these cases, there are ways to simply extend
2653-generic views to handle a larger array of use cases. These situations usually
2654-fall into a handful of patterns dealt with in the sections that follow.
2655-
2656-Making "friendly" template contexts
2657------------------------------------
2658-
2659-You might have noticed that our sample publisher list template stores all the
2660-books in a variable named ``object_list``. While this works just fine, it isn't
2661-all that "friendly" to template authors: they have to "just know" that they're
2662-dealing with publishers here. A better name for that variable would be
2663-``publisher_list``; that variable's content is pretty obvious.
2664-
2665-We can change the name of that variable easily with the ``template_object_name``
2666-argument:
2667-
2668-.. parsed-literal::
2669-
2670-    publisher_info = {
2671-        "queryset" : Publisher.objects.all(),
2672-        **"template_object_name" : "publisher",**
2673-    }
2674-
2675-    urlpatterns = patterns('',
2676-        (r'^publishers/$', list_detail.object_list, publisher_info)
2677-    )
2678-
2679-Providing a useful ``template_object_name`` is always a good idea. Your
2680-coworkers who design templates will thank you.
2681-
2682-Adding extra context
2683---------------------
2684-
2685-Often you simply need to present some extra information beyond that provided by
2686-the generic view. For example, think of showing a list of all the books on each
2687-publisher detail page. The ``object_detail`` generic view provides the
2688-publisher to the context, but it seems there's no way to get additional
2689-information in that template.
2690-
2691-But there is: all generic views take an extra optional parameter,
2692-``extra_context``. This is a dictionary of extra objects that will be added to
2693-the template's context. So, to provide the list of all books on the detail
2694-detail view, we'd use an info dict like this:
2695-
2696-.. parsed-literal::
2697-
2698-    from books.models import Publisher, **Book**
2699-
2700-    publisher_info = {
2701-        "queryset" : Publisher.objects.all(),
2702-        "template_object_name" : "publisher",
2703-        **"extra_context" : {"book_list" : Book.objects.all()}**
2704-    }
2705-
2706-This would populate a ``{{ book_list }}`` variable in the template context.
2707-This pattern can be used to pass any information down into the template for the
2708-generic view. It's very handy.
2709-
2710-However, there's actually a subtle bug here -- can you spot it?
2711-
2712-The problem has to do with when the queries in ``extra_context`` are evaluated.
2713-Because this example puts ``Book.objects.all()`` in the URLconf, it will
2714-be evaluated only once (when the URLconf is first loaded). Once you add or
2715-remove books, you'll notice that the generic view doesn't reflect those
2716-changes until you reload the Web server (see :ref:`caching-and-querysets`
2717-for more information about when QuerySets are cached and evaluated).
2718-
2719-.. note::
2720-
2721-    This problem doesn't apply to the ``queryset`` generic view argument. Since
2722-    Django knows that particular QuerySet should *never* be cached, the generic
2723-    view takes care of clearing the cache when each view is rendered.
2724-
2725-The solution is to use a callback in ``extra_context`` instead of a value. Any
2726-callable (i.e., a function) that's passed to ``extra_context`` will be evaluated
2727-when the view is rendered (instead of only once). You could do this with an
2728-explicitly defined function:
2729-
2730-.. parsed-literal::
2731-
2732-    def get_books():
2733-        return Book.objects.all()
2734-
2735-    publisher_info = {
2736-        "queryset" : Publisher.objects.all(),
2737-        "template_object_name" : "publisher",
2738-        "extra_context" : **{"book_list" : get_books}**
2739-    }
2740-
2741-or you could use a less obvious but shorter version that relies on the fact that
2742-``Book.objects.all`` is itself a callable:
2743-
2744-.. parsed-literal::
2745-
2746-    publisher_info = {
2747-        "queryset" : Publisher.objects.all(),
2748-        "template_object_name" : "publisher",
2749-        "extra_context" : **{"book_list" : Book.objects.all}**
2750-    }
2751-
2752-Notice the lack of parentheses after ``Book.objects.all``; this references
2753-the function without actually calling it (which the generic view will do later).
2754-
2755-Viewing subsets of objects
2756---------------------------
2757-
2758-Now let's take a closer look at this ``queryset`` key we've been using all
2759-along. Most generic views take one of these ``queryset`` arguments -- it's how
2760-the view knows which set of objects to display (see :doc:`/topics/db/queries` for
2761-more information about ``QuerySet`` objects, and see the
2762-:doc:`generic views reference</ref/generic-views>` for the complete details).
2763-
2764-To pick a simple example, we might want to order a list of books by
2765-publication date, with the most recent first:
2766-
2767-.. parsed-literal::
2768-
2769-    book_info = {
2770-        "queryset" : Book.objects.all().order_by("-publication_date"),
2771-    }
2772-
2773-    urlpatterns = patterns('',
2774-        (r'^publishers/$', list_detail.object_list, publisher_info),
2775-        **(r'^books/$', list_detail.object_list, book_info),**
2776-    )
2777-
2778-
2779-That's a pretty simple example, but it illustrates the idea nicely. Of course,
2780-you'll usually want to do more than just reorder objects. If you want to
2781-present a list of books by a particular publisher, you can use the same
2782-technique:
2783-
2784-.. parsed-literal::
2785-
2786-    **acme_books = {**
2787-        **"queryset": Book.objects.filter(publisher__name="Acme Publishing"),**
2788-        **"template_name" : "books/acme_list.html"**
2789-    **}**
2790-
2791-    urlpatterns = patterns('',
2792-        (r'^publishers/$', list_detail.object_list, publisher_info),
2793-        **(r'^books/acme/$', list_detail.object_list, acme_books),**
2794-    )
2795-
2796-Notice that along with a filtered ``queryset``, we're also using a custom
2797-template name. If we didn't, the generic view would use the same template as the
2798-"vanilla" object list, which might not be what we want.
2799-
2800-Also notice that this isn't a very elegant way of doing publisher-specific
2801-books. If we want to add another publisher page, we'd need another handful of
2802-lines in the URLconf, and more than a few publishers would get unreasonable.
2803-We'll deal with this problem in the next section.
2804-
2805-.. note::
2806-
2807-    If you get a 404 when requesting ``/books/acme/``, check to ensure you
2808-    actually have a Publisher with the name 'ACME Publishing'.  Generic
2809-    views have an ``allow_empty`` parameter for this case.  See the
2810-    :doc:`generic views reference</ref/generic-views>` for more details.
2811-
2812-Complex filtering with wrapper functions
2813-----------------------------------------
2814-
2815-Another common need is to filter down the objects given in a list page by some
2816-key in the URL. Earlier we hard-coded the publisher's name in the URLconf, but
2817-what if we wanted to write a view that displayed all the books by some arbitrary
2818-publisher? We can "wrap" the ``object_list`` generic view to avoid writing a lot
2819-of code by hand. As usual, we'll start by writing a URLconf:
2820-
2821-.. parsed-literal::
2822-
2823-    from books.views import books_by_publisher
2824-
2825-    urlpatterns = patterns('',
2826-        (r'^publishers/$', list_detail.object_list, publisher_info),
2827-        **(r'^books/(\\w+)/$', books_by_publisher),**
2828-    )
2829-
2830-Next, we'll write the ``books_by_publisher`` view itself::
2831-
2832-    from django.http import Http404
2833-    from django.views.generic import list_detail
2834-    from books.models import Book, Publisher
2835-
2836-    def books_by_publisher(request, name):
2837-
2838-        # Look up the publisher (and raise a 404 if it can't be found).
2839-        try:
2840-            publisher = Publisher.objects.get(name__iexact=name)
2841-        except Publisher.DoesNotExist:
2842-            raise Http404
2843-
2844-        # Use the object_list view for the heavy lifting.
2845-        return list_detail.object_list(
2846-            request,
2847-            queryset = Book.objects.filter(publisher=publisher),
2848-            template_name = "books/books_by_publisher.html",
2849-            template_object_name = "books",
2850-            extra_context = {"publisher" : publisher}
2851-        )
2852-
2853-This works because there's really nothing special about generic views -- they're
2854-just Python functions. Like any view function, generic views expect a certain
2855-set of arguments and return ``HttpResponse`` objects. Thus, it's incredibly easy
2856-to wrap a small function around a generic view that does additional work before
2857-(or after; see the next section) handing things off to the generic view.
2858-
2859-.. note::
2860-
2861-    Notice that in the preceding example we passed the current publisher being
2862-    displayed in the ``extra_context``. This is usually a good idea in wrappers
2863-    of this nature; it lets the template know which "parent" object is currently
2864-    being browsed.
2865-
2866-Performing extra work
2867----------------------
2868-
2869-The last common pattern we'll look at involves doing some extra work before
2870-or after calling the generic view.
2871-
2872-Imagine we had a ``last_accessed`` field on our ``Author`` object that we were
2873-using to keep track of the last time anybody looked at that author::
2874-
2875-    # models.py
2876-
2877-    class Author(models.Model):
2878-        salutation = models.CharField(max_length=10)
2879-        first_name = models.CharField(max_length=30)
2880-        last_name = models.CharField(max_length=40)
2881-        email = models.EmailField()
2882-        headshot = models.ImageField(upload_to='/tmp')
2883-        last_accessed = models.DateTimeField()
2884-
2885-The generic ``object_detail`` view, of course, wouldn't know anything about this
2886-field, but once again we could easily write a custom view to keep that field
2887-updated.
2888-
2889-First, we'd need to add an author detail bit in the URLconf to point to a
2890-custom view:
2891-
2892-.. parsed-literal::
2893-
2894-    from books.views import author_detail
2895-
2896-    urlpatterns = patterns('',
2897-        #...
2898-        **(r'^authors/(?P<author_id>\\d+)/$', author_detail),**
2899-    )
2900-
2901-Then we'd write our wrapper function::
2902-
2903-    import datetime
2904-    from books.models import Author
2905-    from django.views.generic import list_detail
2906-    from django.shortcuts import get_object_or_404
2907-
2908-    def author_detail(request, author_id):
2909-        # Look up the Author (and raise a 404 if she's not found)
2910-        author = get_object_or_404(Author, pk=author_id)
2911-
2912-        # Record the last accessed date
2913-        author.last_accessed = datetime.datetime.now()
2914-        author.save()
2915-
2916-        # Show the detail page
2917-        return list_detail.object_detail(
2918-            request,
2919-            queryset = Author.objects.all(),
2920-            object_id = author_id,
2921-        )
2922-
2923-.. note::
2924-
2925-    This code won't actually work unless you create a
2926-    ``books/author_detail.html`` template.
2927-
2928-We can use a similar idiom to alter the response returned by the generic view.
2929-If we wanted to provide a downloadable plain-text version of the list of
2930-authors, we could use a view like this::
2931-
2932-    def author_list_plaintext(request):
2933-        response = list_detail.object_list(
2934-            request,
2935-            queryset = Author.objects.all(),
2936-            mimetype = "text/plain",
2937-            template_name = "books/author_list.txt"
2938-        )
2939-        response["Content-Disposition"] = "attachment; filename=authors.txt"
2940-        return response
2941-
2942-This works because the generic views return simple ``HttpResponse`` objects
2943-that can be treated like dictionaries to set HTTP headers. This
2944-``Content-Disposition`` business, by the way, instructs the browser to
2945-download and save the page instead of displaying it in the browser.
2946diff --git a/docs/topics/http/generic-views.txt b/docs/topics/http/generic-views.txt
2947index 15f895e..fdaa27d 100644
2948--- a/docs/topics/http/generic-views.txt
2949+++ b/docs/topics/http/generic-views.txt
2950@@ -2,4 +2,4 @@
2951 Generic views
2952 =============
2953 
2954-See :doc:`/ref/generic-views`.
2955+See :doc:`/ref/class-based-views`.
2956diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt
2957index 73c06ca..ee1d4e8 100644
2958--- a/docs/topics/http/urls.txt
2959+++ b/docs/topics/http/urls.txt
2960@@ -416,8 +416,8 @@ Old::
2961     from django.conf.urls import patterns, url, include
2962 
2963     urlpatterns = patterns('',
2964-        (r'^$', 'django.views.generic.date_based.archive_index'),
2965-        (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'django.views.generic.date_based.archive_month'),
2966+        (r'^$', 'myapp.views.app_index'),
2967+        (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'myapp.views.month_display'),
2968         (r'^tag/(?P<tag>\w+)/$', 'weblog.views.tag'),
2969     )
2970 
2971@@ -425,9 +425,9 @@ New::
2972 
2973     from django.conf.urls import patterns, url, include
2974 
2975-    urlpatterns = patterns('django.views.generic.date_based',
2976-        (r'^$', 'archive_index'),
2977-        (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','archive_month'),
2978+    urlpatterns = patterns('myapp.views',
2979+        (r'^$', 'app_index'),
2980+        (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','month_display'),
2981     )
2982 
2983     urlpatterns += patterns('weblog.views',
2984@@ -579,7 +579,7 @@ In this example, for a request to ``/blog/2005/``, Django will call the
2985 
2986     year='2005', foo='bar'
2987 
2988-This technique is used in :doc:`generic views </ref/generic-views>` and in the
2989+This technique is used in the
2990 :doc:`syndication framework </ref/contrib/syndication>` to pass metadata and
2991 options to views.
2992 
2993diff --git a/docs/topics/index.txt b/docs/topics/index.txt
2994index 4b33099..95ca76e 100644
2995--- a/docs/topics/index.txt
2996+++ b/docs/topics/index.txt
2997@@ -12,7 +12,6 @@ Introductions to all the key parts of Django you'll need to know:
2998    forms/index
2999    templates
3000    class-based-views
3001-   generic-views-migration
3002    files
3003    testing
3004    auth
3005@@ -27,11 +26,3 @@ Introductions to all the key parts of Django you'll need to know:
3006    serialization
3007    settings
3008    signals
3009-
3010-Deprecated features
3011--------------------
3012-
3013-.. toctree::
3014-   :maxdepth: 1
3015-
3016-   generic-views
3017diff --git a/tests/regressiontests/special_headers/tests.py b/tests/regressiontests/special_headers/tests.py
3018index 4de518c..087bfe9 100644
3019--- a/tests/regressiontests/special_headers/tests.py
3020+++ b/tests/regressiontests/special_headers/tests.py
3021@@ -1,5 +1,3 @@
3022-import warnings
3023-
3024 from django.contrib.auth.models import User
3025 from django.test import TestCase
3026 
3027@@ -8,14 +6,6 @@ class SpecialHeadersTest(TestCase):
3028     fixtures = ['data.xml']
3029     urls = 'regressiontests.special_headers.urls'
3030 
3031-    def setUp(self):
3032-        self.save_warnings_state()
3033-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3034-                                module='django.views.generic.list_detail')
3035-
3036-    def tearDown(self):
3037-        self.restore_warnings_state()
3038-
3039     def test_xheaders(self):
3040         user = User.objects.get(username='super')
3041         response = self.client.get('/special_headers/article/1/')
3042diff --git a/tests/regressiontests/special_headers/urls.py b/tests/regressiontests/special_headers/urls.py
3043index 2e6a305..f7ba141 100644
3044--- a/tests/regressiontests/special_headers/urls.py
3045+++ b/tests/regressiontests/special_headers/urls.py
3046@@ -2,13 +2,12 @@
3047 from __future__ import absolute_import
3048 
3049 from django.conf.urls import patterns
3050-from django.views.generic.list_detail import object_detail
3051 
3052 from . import views
3053 from .models import Article
3054 
3055 urlpatterns = patterns('',
3056-    (r'^special_headers/article/(?P<object_id>\d+)/$', object_detail, {'queryset': Article.objects.all()}),
3057+    (r'^special_headers/article/(?P<object_id>\d+)/$', views.xview_xheaders),
3058     (r'^special_headers/xview/func/$', views.xview_dec(views.xview)),
3059     (r'^special_headers/xview/class/$', views.xview_dec(views.XViewClass.as_view())),
3060 )
3061diff --git a/tests/regressiontests/special_headers/views.py b/tests/regressiontests/special_headers/views.py
3062index ce94036..a8bbd65 100644
3063--- a/tests/regressiontests/special_headers/views.py
3064+++ b/tests/regressiontests/special_headers/views.py
3065@@ -1,14 +1,21 @@
3066-# -*- coding:utf-8 -*-
3067+from django.core.xheaders import populate_xheaders
3068 from django.http import HttpResponse
3069 from django.utils.decorators import decorator_from_middleware
3070 from django.views.generic import View
3071 from django.middleware.doc import XViewMiddleware
3072 
3073+from .models import Article
3074+
3075 xview_dec = decorator_from_middleware(XViewMiddleware)
3076 
3077 def xview(request):
3078     return HttpResponse()
3079 
3080+def xview_xheaders(request, object_id):
3081+    response = HttpResponse()
3082+    populate_xheaders(request, response, Article, 1)
3083+    return response
3084+
3085 class XViewClass(View):
3086     def get(self, request):
3087         return HttpResponse()
3088diff --git a/tests/regressiontests/views/generic_urls.py b/tests/regressiontests/views/generic_urls.py
3089index 40a6c01..5bf929e 100644
3090--- a/tests/regressiontests/views/generic_urls.py
3091+++ b/tests/regressiontests/views/generic_urls.py
3092@@ -2,6 +2,7 @@
3093 from __future__ import absolute_import
3094 
3095 from django.conf.urls import patterns, url
3096+from django.views.generic import RedirectView
3097 
3098 from . import views
3099 from .models import Article, DateArticle, UrlArticle
3100@@ -35,65 +36,12 @@ urlpatterns = patterns('',
3101     url(u'^中文/target/$', 'regressiontests.views.views.index_page'),
3102 )
3103 
3104-# Date-based generic views.
3105-urlpatterns += patterns('django.views.generic.date_based',
3106-    (r'^date_based/object_detail/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>[-\w]+)/$',
3107-        'object_detail',
3108-        dict(slug_field='slug', **date_based_info_dict)),
3109-    (r'^date_based/object_detail/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>[-\w]+)/allow_future/$',
3110-        'object_detail',
3111-        dict(allow_future=True, slug_field='slug', **date_based_info_dict)),
3112-    (r'^date_based/archive_day/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$',
3113-        'archive_day',
3114-        numeric_days_info_dict),
3115-    (r'^date_based/archive_month/(?P<year>\d{4})/(?P<month>\d{1,2})/$',
3116-        'archive_month',
3117-        date_based_info_dict),
3118-    (r'^date_based/datefield/archive_month/(?P<year>\d{4})/(?P<month>\d{1,2})/$',
3119-        'archive_month',
3120-        date_based_datefield_info_dict),
3121-)
3122-
3123-# crud generic views.
3124-urlpatterns += patterns('django.views.generic.create_update',
3125-    (r'^create_update/member/create/article/$', 'create_object',
3126-        dict(login_required=True, model=Article)),
3127-    (r'^create_update/create/article/$', 'create_object',
3128-        dict(post_save_redirect='/create_update/view/article/%(slug)s/',
3129-             model=Article)),
3130-    (r'^create_update/update/article/(?P<slug>[-\w]+)/$', 'update_object',
3131-        dict(post_save_redirect='/create_update/view/article/%(slug)s/',
3132-             slug_field='slug', model=Article)),
3133-    (r'^create_update/create_custom/article/$', views.custom_create),
3134-    (r'^create_update/delete/article/(?P<slug>[-\w]+)/$', 'delete_object',
3135-        dict(post_delete_redirect='/create_update/', slug_field='slug',
3136-             model=Article)),
3137-
3138-    # No post_save_redirect and no get_absolute_url on model.
3139-    (r'^create_update/no_redirect/create/article/$', 'create_object',
3140-        dict(model=Article)),
3141-    (r'^create_update/no_redirect/update/article/(?P<slug>[-\w]+)/$',
3142-        'update_object', dict(slug_field='slug', model=Article)),
3143-
3144-    # get_absolute_url on model, but no passed post_save_redirect.
3145-    (r'^create_update/no_url/create/article/$', 'create_object',
3146-        dict(model=UrlArticle)),
3147-    (r'^create_update/no_url/update/article/(?P<slug>[-\w]+)/$',
3148-        'update_object', dict(slug_field='slug', model=UrlArticle)),
3149-)
3150-
3151-urlpatterns += patterns('django.views.generic.list_detail',
3152-    (r'^object_list/page(?P<page>[\w]*)/$', 'object_list', object_list_dict),
3153-    (r'^object_list_no_paginate_by/page(?P<page>[0-9]+)/$', 'object_list',
3154-     object_list_no_paginate_by),
3155-)
3156-
3157 # rediriects, both temporary and permanent, with non-ASCII targets
3158-urlpatterns += patterns('django.views.generic.simple',
3159-    ('^nonascii_redirect/$', 'redirect_to',
3160-        {'url': u'/中文/target/', 'permanent': False}),
3161-    ('^permanent_nonascii_redirect/$', 'redirect_to',
3162-        {'url': u'/中文/target/', 'permanent': True}),
3163+urlpatterns += patterns('',
3164+    ('^nonascii_redirect/$', RedirectView.as_view(
3165+        url=u'/中文/target/', permanent=False)),
3166+    ('^permanent_nonascii_redirect/$', RedirectView.as_view(
3167+        url=u'/中文/target/', permanent=True)),
3168 )
3169 
3170 urlpatterns += patterns('regressiontests.views.views',
3171@@ -107,13 +55,3 @@ urlpatterns += patterns('regressiontests.views.views',
3172     (r'^shortcuts/render/current_app/$', 'render_view_with_current_app'),
3173     (r'^shortcuts/render/current_app_conflict/$', 'render_view_with_current_app_conflict'),
3174 )
3175-
3176-# simple generic views.
3177-urlpatterns += patterns('django.views.generic.simple',
3178-    (r'^simple/redirect_to/$', 'redirect_to', dict(url='/simple/target/')),
3179-    (r'^simple/redirect_to_temp/$', 'redirect_to', dict(url='/simple/target/', permanent=False)),
3180-    (r'^simple/redirect_to_none/$', 'redirect_to', dict(url=None)),
3181-    (r'^simple/redirect_to_arg/(?P<id>\d+)/$', 'redirect_to', dict(url='/simple/target_arg/%(id)s/')),
3182-    (r'^simple/redirect_to_query/$', 'redirect_to', dict(url='/simple/target/', query_string=True)),
3183-    (r'^simple/redirect_to_arg_and_query/(?P<id>\d+)/$', 'redirect_to', dict(url='/simple/target_arg/%(id)s/', query_string=True)),
3184-)
3185diff --git a/tests/regressiontests/views/tests/__init__.py b/tests/regressiontests/views/tests/__init__.py
3186index 04537a2..63db5da 100644
3187--- a/tests/regressiontests/views/tests/__init__.py
3188+++ b/tests/regressiontests/views/tests/__init__.py
3189@@ -4,11 +4,6 @@ from .debug import (DebugViewTests, ExceptionReporterTests,
3190     ExceptionReporterTests, PlainTextReportTests, ExceptionReporterFilterTests,
3191     AjaxResponseExceptionReporterFilter)
3192 from .defaults import DefaultsTests
3193-from .generic.create_update import (UpdateDeleteObjectTest, CreateObjectTest,
3194-    PostSaveRedirectTests, NoPostSaveNoAbsoluteUrl, AbsoluteUrlNoPostSave)
3195-from .generic.date_based import MonthArchiveTest, ObjectDetailTest, DayArchiveTests
3196-from .generic.object_list import ObjectListTest
3197-from .generic.simple import RedirectToTest
3198 from .i18n import JsI18NTests, I18NTests, JsI18NTestsMultiPackage
3199 from .shortcuts import ShortcutTests
3200 from .specials import URLHandling
3201diff --git a/tests/regressiontests/views/tests/generic/__init__.py b/tests/regressiontests/views/tests/generic/__init__.py
3202deleted file mode 100644
3203index e69de29..0000000
3204diff --git a/tests/regressiontests/views/tests/generic/create_update.py b/tests/regressiontests/views/tests/generic/create_update.py
3205deleted file mode 100644
3206index 2abcfb4..0000000
3207--- a/tests/regressiontests/views/tests/generic/create_update.py
3208+++ /dev/null
3209@@ -1,255 +0,0 @@
3210-import datetime
3211-import warnings
3212-
3213-from django.test import TestCase
3214-from django.core.exceptions import ImproperlyConfigured
3215-from regressiontests.views.models import Article, UrlArticle
3216-
3217-class CreateObjectTest(TestCase):
3218-    fixtures = ['testdata.json']
3219-    urls = 'regressiontests.views.generic_urls'
3220-
3221-    def setUp(self):
3222-        self.save_warnings_state()
3223-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3224-                                module='django.views.generic.create_update')
3225-
3226-    def tearDown(self):
3227-        self.restore_warnings_state()
3228-
3229-    def test_login_required_view(self):
3230-        """
3231-        Verifies that an unauthenticated user attempting to access a
3232-        login_required view gets redirected to the login page and that
3233-        an authenticated user is let through.
3234-        """
3235-        view_url = '/create_update/member/create/article/'
3236-        response = self.client.get(view_url)
3237-        self.assertRedirects(response, '/accounts/login/?next=%s' % view_url)
3238-        # Now login and try again.
3239-        login = self.client.login(username='testclient', password='password')
3240-        self.assertTrue(login, 'Could not log in')
3241-        response = self.client.get(view_url)
3242-        self.assertEqual(response.status_code, 200)
3243-        self.assertTemplateUsed(response, 'views/article_form.html')
3244-
3245-    def test_create_article_display_page(self):
3246-        """
3247-        Ensures the generic view returned the page and contains a form.
3248-        """
3249-        view_url = '/create_update/create/article/'
3250-        response = self.client.get(view_url)
3251-        self.assertEqual(response.status_code, 200)
3252-        self.assertTemplateUsed(response, 'views/article_form.html')
3253-        if not response.context.get('form'):
3254-            self.fail('No form found in the response.')
3255-
3256-    def test_create_article_with_errors(self):
3257-        """
3258-        POSTs a form that contains validation errors.
3259-        """
3260-        view_url = '/create_update/create/article/'
3261-        num_articles = Article.objects.count()
3262-        response = self.client.post(view_url, {
3263-            'title': 'My First Article',
3264-        })
3265-        self.assertFormError(response, 'form', 'slug', [u'This field is required.'])
3266-        self.assertTemplateUsed(response, 'views/article_form.html')
3267-        self.assertEqual(num_articles, Article.objects.count(),
3268-                         "Number of Articles should not have changed.")
3269-
3270-    def test_create_custom_save_article(self):
3271-        """
3272-        Creates a new article using a custom form class with a save method
3273-        that alters the slug entered.
3274-        """
3275-        view_url = '/create_update/create_custom/article/'
3276-        response = self.client.post(view_url, {
3277-            'title': 'Test Article',
3278-            'slug': 'this-should-get-replaced',
3279-            'author': 1,
3280-            'date_created': datetime.datetime(2007, 6, 25),
3281-        })
3282-        self.assertRedirects(response,
3283-            '/create_update/view/article/some-other-slug/',
3284-            target_status_code=404)
3285-
3286-class UpdateDeleteObjectTest(TestCase):
3287-    fixtures = ['testdata.json']
3288-    urls = 'regressiontests.views.generic_urls'
3289-
3290-    def setUp(self):
3291-        self.save_warnings_state()
3292-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3293-                                module='django.views.generic.create_update')
3294-
3295-    def tearDown(self):
3296-        self.restore_warnings_state()
3297-
3298-    def test_update_object_form_display(self):
3299-        """
3300-        Verifies that the form was created properly and with initial values.
3301-        """
3302-        response = self.client.get('/create_update/update/article/old_article/')
3303-        self.assertTemplateUsed(response, 'views/article_form.html')
3304-        self.assertHTMLEqual(unicode(response.context['form']['title']),
3305-            u'<input id="id_title" type="text" name="title" value="Old Article" maxlength="100" />')
3306-
3307-    def test_update_object(self):
3308-        """
3309-        Verifies the updating of an Article.
3310-        """
3311-        response = self.client.post('/create_update/update/article/old_article/', {
3312-            'title': 'Another Article',
3313-            'slug': 'another-article-slug',
3314-            'author': 1,
3315-            'date_created': datetime.datetime(2007, 6, 25),
3316-        })
3317-        article = Article.objects.get(pk=1)
3318-        self.assertEqual(article.title, "Another Article")
3319-
3320-    def test_delete_object_confirm(self):
3321-        """
3322-        Verifies the confirm deletion page is displayed using a GET.
3323-        """
3324-        response = self.client.get('/create_update/delete/article/old_article/')
3325-        self.assertTemplateUsed(response, 'views/article_confirm_delete.html')
3326-
3327-    def test_delete_object(self):
3328-        """
3329-        Verifies the object actually gets deleted on a POST.
3330-        """
3331-        view_url = '/create_update/delete/article/old_article/'
3332-        response = self.client.post(view_url)
3333-        try:
3334-            Article.objects.get(slug='old_article')
3335-        except Article.DoesNotExist:
3336-            pass
3337-        else:
3338-            self.fail('Object was not deleted.')
3339-
3340-class PostSaveRedirectTests(TestCase):
3341-    """
3342-    Verifies that the views redirect to the correct locations depending on
3343-    if a post_save_redirect was passed and a get_absolute_url method exists
3344-    on the Model.
3345-    """
3346-
3347-    fixtures = ['testdata.json']
3348-    article_model = Article
3349-    urls = 'regressiontests.views.generic_urls'
3350-
3351-    create_url = '/create_update/create/article/'
3352-    update_url = '/create_update/update/article/old_article/'
3353-    delete_url = '/create_update/delete/article/old_article/'
3354-
3355-    create_redirect = '/create_update/view/article/my-first-article/'
3356-    update_redirect = '/create_update/view/article/another-article-slug/'
3357-    delete_redirect = '/create_update/'
3358-
3359-    def setUp(self):
3360-        self.save_warnings_state()
3361-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3362-                                module='django.views.generic.create_update')
3363-
3364-    def tearDown(self):
3365-        self.restore_warnings_state()
3366-
3367-    def test_create_article(self):
3368-        num_articles = self.article_model.objects.count()
3369-        response = self.client.post(self.create_url, {
3370-            'title': 'My First Article',
3371-            'slug': 'my-first-article',
3372-            'author': '1',
3373-            'date_created': datetime.datetime(2007, 6, 25),
3374-        })
3375-        self.assertRedirects(response, self.create_redirect,
3376-                             target_status_code=404)
3377-        self.assertEqual(num_articles + 1, self.article_model.objects.count(),
3378-                         "A new Article should have been created.")
3379-
3380-    def test_update_article(self):
3381-        num_articles = self.article_model.objects.count()
3382-        response = self.client.post(self.update_url, {
3383-            'title': 'Another Article',
3384-            'slug': 'another-article-slug',
3385-            'author': 1,
3386-            'date_created': datetime.datetime(2007, 6, 25),
3387-        })
3388-        self.assertRedirects(response, self.update_redirect,
3389-                             target_status_code=404)
3390-        self.assertEqual(num_articles, self.article_model.objects.count(),
3391-                         "A new Article should not have been created.")
3392-
3393-    def test_delete_article(self):
3394-        num_articles = self.article_model.objects.count()
3395-        response = self.client.post(self.delete_url)
3396-        self.assertRedirects(response, self.delete_redirect,
3397-                             target_status_code=404)
3398-        self.assertEqual(num_articles - 1, self.article_model.objects.count(),
3399-                         "An Article should have been deleted.")
3400-
3401-class NoPostSaveNoAbsoluteUrl(PostSaveRedirectTests):
3402-    """
3403-    Tests that when no post_save_redirect is passed and no get_absolute_url
3404-    method exists on the Model that the view raises an ImproperlyConfigured
3405-    error.
3406-    """
3407-    urls = 'regressiontests.views.generic_urls'
3408-
3409-    create_url = '/create_update/no_redirect/create/article/'
3410-    update_url = '/create_update/no_redirect/update/article/old_article/'
3411-
3412-    def setUp(self):
3413-        self.save_warnings_state()
3414-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3415-                                module='django.views.generic.create_update')
3416-
3417-    def tearDown(self):
3418-        self.restore_warnings_state()
3419-
3420-    def test_create_article(self):
3421-        self.assertRaises(ImproperlyConfigured,
3422-            super(NoPostSaveNoAbsoluteUrl, self).test_create_article)
3423-
3424-    def test_update_article(self):
3425-        self.assertRaises(ImproperlyConfigured,
3426-            super(NoPostSaveNoAbsoluteUrl, self).test_update_article)
3427-
3428-    def test_delete_article(self):
3429-        """
3430-        The delete_object view requires a post_delete_redirect, so skip testing
3431-        here.
3432-        """
3433-        pass
3434-
3435-class AbsoluteUrlNoPostSave(PostSaveRedirectTests):
3436-    """
3437-    Tests that the views redirect to the Model's get_absolute_url when no
3438-    post_save_redirect is passed.
3439-    """
3440-    urls = 'regressiontests.views.generic_urls'
3441-
3442-    # Article model with get_absolute_url method.
3443-    article_model = UrlArticle
3444-
3445-    create_url = '/create_update/no_url/create/article/'
3446-    update_url = '/create_update/no_url/update/article/old_article/'
3447-
3448-    create_redirect = '/urlarticles/my-first-article/'
3449-    update_redirect = '/urlarticles/another-article-slug/'
3450-
3451-    def setUp(self):
3452-        self.save_warnings_state()
3453-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3454-                                module='django.views.generic.create_update')
3455-
3456-    def tearDown(self):
3457-        self.restore_warnings_state()
3458-
3459-    def test_delete_article(self):
3460-        """
3461-        The delete_object view requires a post_delete_redirect, so skip testing
3462-        here.
3463-        """
3464-        pass
3465diff --git a/tests/regressiontests/views/tests/generic/date_based.py b/tests/regressiontests/views/tests/generic/date_based.py
3466deleted file mode 100644
3467index 96555e5..0000000
3468--- a/tests/regressiontests/views/tests/generic/date_based.py
3469+++ /dev/null
3470@@ -1,171 +0,0 @@
3471-# coding: utf-8
3472-import warnings
3473-
3474-from django.test import TestCase
3475-from datetime import datetime, date
3476-from datetime import timedelta
3477-from regressiontests.views.models import Article, Author, DateArticle
3478-
3479-class ObjectDetailTest(TestCase):
3480-    fixtures = ['testdata.json']
3481-    urls = 'regressiontests.views.generic_urls'
3482-
3483-    def setUp(self):
3484-        self.save_warnings_state()
3485-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3486-                                module='django.views.generic.date_based')
3487-        # Correct the date for the current article
3488-        current_article = Article.objects.get(title="Current Article")
3489-        current_article.date_created = datetime.now()
3490-        current_article.save()
3491-
3492-    def tearDown(self):
3493-        self.restore_warnings_state()
3494-
3495-    def test_finds_past(self):
3496-        "date_based.object_detail can view a page in the past"
3497-        response = self.client.get('/date_based/object_detail/2001/01/01/old_article/')
3498-        self.assertEqual(response.status_code, 200)
3499-        self.assertEqual(response.context['object'].title, "Old Article")
3500-
3501-    def test_object_detail_finds_today(self):
3502-        "date_based.object_detail can view a page from today"
3503-        today_url = datetime.now().strftime('%Y/%m/%d')
3504-        response = self.client.get('/date_based/object_detail/%s/current_article/' % today_url)
3505-        self.assertEqual(response.status_code, 200)
3506-        self.assertEqual(response.context['object'].title, "Current Article")
3507-
3508-    def test_object_detail_ignores_future(self):
3509-        "date_based.object_detail can view a page from the future, but only if allowed."
3510-        response = self.client.get('/date_based/object_detail/3000/01/01/future_article/')
3511-        self.assertEqual(response.status_code, 404)
3512-
3513-    def test_object_detail_allowed_future_if_enabled(self):
3514-        "date_based.object_detail can view a page from the future if explicitly allowed."
3515-        response = self.client.get('/date_based/object_detail/3000/01/01/future_article/allow_future/')
3516-        self.assertEqual(response.status_code, 200)
3517-        self.assertEqual(response.context['object'].title, "Future Article")
3518-
3519-class MonthArchiveTest(TestCase):
3520-    urls = 'regressiontests.views.generic_urls'
3521-
3522-    def setUp(self):
3523-        self.save_warnings_state()
3524-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3525-                                module='django.views.generic.date_based')
3526-
3527-    def tearDown(self):
3528-        self.restore_warnings_state()
3529-
3530-    def test_archive_month_includes_only_month(self):
3531-        "Regression for #3031: Archives around Feburary include only one month"
3532-        author = Author(name="John Smith")
3533-        author.save()
3534-
3535-        # 2004 was a leap year, so it should be weird enough to not cheat
3536-        first_second_of_feb = datetime(2004, 2, 1, 0, 0, 1)
3537-        first_second_of_mar = datetime(2004, 3, 1, 0, 0, 1)
3538-        two_seconds = timedelta(0, 2, 0)
3539-        article = Article(title="example", author=author)
3540-
3541-        article.date_created = first_second_of_feb
3542-        article.save()
3543-        response = self.client.get('/date_based/archive_month/2004/02/')
3544-        self.assertEqual(response.status_code, 200)
3545-        self.assertEqual(response.context['next_month'], date(2004, 3, 1))
3546-        self.assertEqual(response.context['previous_month'], date(2004, 1, 1))
3547-
3548-        article.date_created = first_second_of_feb-two_seconds
3549-        article.save()
3550-        response = self.client.get('/date_based/archive_month/2004/02/')
3551-        self.assertEqual(response.status_code, 404)
3552-
3553-        article.date_created = first_second_of_mar-two_seconds
3554-        article.save()
3555-        response = self.client.get('/date_based/archive_month/2004/02/')
3556-        self.assertEqual(response.status_code, 200)
3557-        self.assertEqual(response.context['next_month'], date(2004, 3, 1))
3558-        self.assertEqual(response.context['previous_month'], date(2004, 1, 1))
3559-
3560-        article.date_created = first_second_of_mar
3561-        article.save()
3562-        response = self.client.get('/date_based/archive_month/2004/02/')
3563-        self.assertEqual(response.status_code, 404)
3564-
3565-        article2 = DateArticle(title="example", author=author)
3566-
3567-        article2.date_created = first_second_of_feb.date()
3568-        article2.save()
3569-        response = self.client.get('/date_based/datefield/archive_month/2004/02/')
3570-        self.assertEqual(response.status_code, 200)
3571-        self.assertEqual(response.context['next_month'], date(2004, 3, 1))
3572-        self.assertEqual(response.context['previous_month'], date(2004, 1, 1))
3573-
3574-        article2.date_created = (first_second_of_feb-two_seconds).date()
3575-        article2.save()
3576-        response = self.client.get('/date_based/datefield/archive_month/2004/02/')
3577-        self.assertEqual(response.status_code, 404)
3578-
3579-        article2.date_created = (first_second_of_mar-two_seconds).date()
3580-        article2.save()
3581-        response = self.client.get('/date_based/datefield/archive_month/2004/02/')
3582-        self.assertEqual(response.status_code, 200)
3583-        self.assertEqual(response.context['next_month'], date(2004, 3, 1))
3584-        self.assertEqual(response.context['previous_month'], date(2004, 1, 1))
3585-
3586-        article2.date_created = first_second_of_mar.date()
3587-        article2.save()
3588-        response = self.client.get('/date_based/datefield/archive_month/2004/02/')
3589-        self.assertEqual(response.status_code, 404)
3590-
3591-        now = datetime.now()
3592-        prev_month = now.date().replace(day=1)
3593-        if prev_month.month == 1:
3594-            prev_month = prev_month.replace(year=prev_month.year-1, month=12)
3595-        else:
3596-            prev_month = prev_month.replace(month=prev_month.month-1)
3597-        article2.date_created = now
3598-        article2.save()
3599-        response = self.client.get('/date_based/datefield/archive_month/%s/' % now.strftime('%Y/%m'))
3600-        self.assertEqual(response.status_code, 200)
3601-        self.assertEqual(response.context['next_month'], None)
3602-        self.assertEqual(response.context['previous_month'], prev_month)
3603-       
3604-    def test_archive_month_date_list(self):
3605-        author = Author(name="John Smith")
3606-        author.save()
3607-        date1 = datetime(2010, 1, 1, 0, 0, 0)
3608-        date2 = datetime(2010, 1, 2, 0, 0, 0)
3609-        Article.objects.create(title='example1', author=author, date_created=date1)
3610-        Article.objects.create(title='example2', author=author, date_created=date2)
3611-        response = self.client.get('/date_based/archive_month/2010/1/')
3612-        self.assertEqual(response.status_code, 200)
3613-        self.assertEqual(len(response.context['date_list']), 2)
3614-        self.assertEqual(response.context['date_list'][0], date1)
3615-        # Checks that the same date is not included more than once in the list
3616-        Article.objects.create(title='example2', author=author, date_created=date2)
3617-        response = self.client.get('/date_based/archive_month/2010/1/')
3618-        self.assertEqual(len(response.context['date_list']), 2)
3619-
3620-class DayArchiveTests(TestCase):
3621-    urls = 'regressiontests.views.generic_urls'
3622-
3623-    def setUp(self):
3624-        self.save_warnings_state()
3625-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3626-                                module='django.views.generic.date_based')
3627-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3628-                                module='django.views.generic.create_update')
3629-
3630-    def tearDown(self):
3631-        self.restore_warnings_state()
3632-
3633-    def test_year_month_day_format(self):
3634-        """
3635-        Make sure day views don't get confused with numeric month formats (#7944)
3636-        """
3637-        author = Author.objects.create(name="John Smith")
3638-        article = Article.objects.create(title="example", author=author, date_created=datetime(2004, 1, 21, 0, 0, 1))
3639-        response = self.client.get('/date_based/archive_day/2004/1/21/')
3640-        self.assertEqual(response.status_code, 200)
3641-        self.assertEqual(response.context['object_list'][0], article)
3642diff --git a/tests/regressiontests/views/tests/generic/object_list.py b/tests/regressiontests/views/tests/generic/object_list.py
3643deleted file mode 100644
3644index 3fa871a..0000000
3645--- a/tests/regressiontests/views/tests/generic/object_list.py
3646+++ /dev/null
3647@@ -1,47 +0,0 @@
3648-import warnings
3649-
3650-from django.test import TestCase
3651-
3652-
3653-class ObjectListTest(TestCase):
3654-    fixtures = ['testdata.json']
3655-    urls = 'regressiontests.views.generic_urls'
3656-
3657-    def setUp(self):
3658-        self.save_warnings_state()
3659-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3660-                                module='django.views.generic.list_detail')
3661-
3662-    def tearDown(self):
3663-        self.restore_warnings_state()
3664-
3665-    def check_pagination(self, url, expected_status_code, object_count=None):
3666-        response = self.client.get(url)
3667-        self.assertEqual(response.status_code, expected_status_code)
3668-
3669-        if object_count:
3670-            self.assertEqual(response.context['is_paginated'], True)
3671-            self.assertEqual(len(response.context['page_obj'].object_list),
3672-                             object_count)
3673-
3674-        return response
3675-
3676-    def test_finds_pages(self):
3677-        # Check page count doesn't start at 0.
3678-        self.check_pagination('/object_list/page0/', 404)
3679-
3680-        # Check basic pages.
3681-        self.check_pagination('/object_list/page/', 200, 2)
3682-        self.check_pagination('/object_list/page1/', 200, 2)
3683-        self.check_pagination('/object_list/page2/', 200, 1)
3684-        self.check_pagination('/object_list/page3/', 404)
3685-
3686-        # Check the special "last" page.
3687-        self.check_pagination('/object_list/pagelast/', 200, 1)
3688-        self.check_pagination('/object_list/pagenotlast/', 404)
3689-
3690-    def test_no_paginate_by(self):
3691-        # Ensure that the view isn't paginated by default.
3692-        url = '/object_list_no_paginate_by/page1/'
3693-        response = self.check_pagination(url, 200)
3694-        self.assertEqual(response.context['is_paginated'], False)
3695diff --git a/tests/regressiontests/views/tests/generic/simple.py b/tests/regressiontests/views/tests/generic/simple.py
3696deleted file mode 100644
3697index 7dcf08a..0000000
3698--- a/tests/regressiontests/views/tests/generic/simple.py
3699+++ /dev/null
3700@@ -1,64 +0,0 @@
3701-# coding: utf-8
3702-import warnings
3703-
3704-from django.test import TestCase
3705-
3706-class RedirectToTest(TestCase):
3707-    urls = 'regressiontests.views.generic_urls'
3708-
3709-    def setUp(self):
3710-        self.save_warnings_state()
3711-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3712-                                module='django.views.generic.simple')
3713-
3714-    def tearDown(self):
3715-        self.restore_warnings_state()
3716-
3717-    def test_redirect_to_returns_permanent_redirect(self):
3718-        "simple.redirect_to returns a permanent redirect (301) by default"
3719-        response = self.client.get('/simple/redirect_to/')
3720-        self.assertEqual(response.status_code, 301)
3721-        self.assertEqual('http://testserver/simple/target/', response['Location'])
3722-
3723-    def test_redirect_to_can_return_a_temporary_redirect(self):
3724-        "simple.redirect_to returns a temporary redirect (302) when explicitely asked to"
3725-        response = self.client.get('/simple/redirect_to_temp/')
3726-        self.assertEqual(response.status_code, 302)
3727-        self.assertEqual('http://testserver/simple/target/', response['Location'])
3728-
3729-    def test_redirect_to_on_empty_url_returns_gone(self):
3730-        "simple.redirect_to returns resource gone (410) when given a None url"
3731-        response = self.client.get('/simple/redirect_to_none/')
3732-        self.assertEqual(response.status_code, 410)
3733-
3734-    def test_redirect_to_allows_formatted_url_string(self):
3735-        "simple.redirect_to uses string interpolation on target url for keyword args"
3736-        response = self.client.get('/simple/redirect_to_arg/42/')
3737-        self.assertEqual(response.status_code, 301)
3738-        self.assertEqual('http://testserver/simple/target_arg/42/', response['Location'])
3739-
3740-    def test_redirect_to_allows_query_string_to_be_passed(self):
3741-        "simple.redirect_to configured with query_string=True passes on any query string"
3742-        # the default is to not forward the query string
3743-        response = self.client.get('/simple/redirect_to/?param1=foo&param2=bar')
3744-        self.assertEqual(response.status_code, 301)
3745-        self.assertEqual('http://testserver/simple/target/', response['Location'])
3746-        # views configured with query_string=True however passes the query string along
3747-        response = self.client.get('/simple/redirect_to_query/?param1=foo&param2=bar')
3748-        self.assertEqual(response.status_code, 301)
3749-        self.assertEqual('http://testserver/simple/target/?param1=foo&param2=bar', response['Location'])
3750-
3751-        # Confirm that the contents of the query string are not subject to
3752-        # string interpolation (Refs #17111):
3753-        response = self.client.get('/simple/redirect_to_query/?param1=foo&param2=hist%C3%B3ria')
3754-        self.assertEqual(response.status_code, 301)
3755-        self.assertEqual('http://testserver/simple/target/?param1=foo&param2=hist%C3%B3ria', response['Location'])
3756-        response = self.client.get('/simple/redirect_to_arg_and_query/99/?param1=foo&param2=hist%C3%B3ria')
3757-        self.assertEqual(response.status_code, 301)
3758-        self.assertEqual('http://testserver/simple/target_arg/99/?param1=foo&param2=hist%C3%B3ria', response['Location'])
3759-
3760-    def test_redirect_to_when_meta_contains_no_query_string(self):
3761-        "regression for #16705"
3762-        # we can't use self.client.get because it always sets QUERY_STRING
3763-        response = self.client.request(PATH_INFO='/simple/redirect_to/')
3764-        self.assertEqual(response.status_code, 301)
3765diff --git a/tests/regressiontests/views/tests/shortcuts.py b/tests/regressiontests/views/tests/shortcuts.py
3766index d20b6d1..a48bb25 100644
3767--- a/tests/regressiontests/views/tests/shortcuts.py
3768+++ b/tests/regressiontests/views/tests/shortcuts.py
3769@@ -1,5 +1,3 @@
3770-import warnings
3771-
3772 from django.conf import settings
3773 from django.test import TestCase
3774 from django.test.utils import override_settings
3775@@ -11,14 +9,6 @@ from django.test.utils import override_settings
3776 class ShortcutTests(TestCase):
3777     urls = 'regressiontests.views.generic_urls'
3778 
3779-    def setUp(self):
3780-        self.save_warnings_state()
3781-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3782-                                module='django.views.generic.simple')
3783-
3784-    def tearDown(self):
3785-        self.restore_warnings_state()
3786-
3787     def test_render_to_response(self):
3788         response = self.client.get('/shortcuts/render_to_response/')
3789         self.assertEqual(response.status_code, 200)
3790diff --git a/tests/regressiontests/views/tests/specials.py b/tests/regressiontests/views/tests/specials.py
3791index 7855704..cd8ac5b 100644
3792--- a/tests/regressiontests/views/tests/specials.py
3793+++ b/tests/regressiontests/views/tests/specials.py
3794@@ -1,6 +1,4 @@
3795 # coding: utf-8
3796-import warnings
3797-
3798 from django.test import TestCase
3799 
3800 
3801@@ -11,14 +9,6 @@ class URLHandling(TestCase):
3802     urls = 'regressiontests.views.generic_urls'
3803     redirect_target = "/%E4%B8%AD%E6%96%87/target/"
3804 
3805-    def setUp(self):
3806-        self.save_warnings_state()
3807-        warnings.filterwarnings('ignore', category=DeprecationWarning,
3808-                                module='django.views.generic.simple')
3809-
3810-    def tearDown(self):
3811-        self.restore_warnings_state()
3812-
3813     def test_combining_redirect(self):
3814         """
3815         Tests that redirecting to an IRI, requiring encoding before we use it
3816diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
3817index 1d17e6e..8e530cd 100644
3818--- a/tests/regressiontests/views/views.py
3819+++ b/tests/regressiontests/views/views.py
3820@@ -21,25 +21,6 @@ def index_page(request):
3821     """Dummy index page"""
3822     return HttpResponse('<html><body>Dummy page</body></html>')
3823 
3824-def custom_create(request):
3825-    """
3826-    Calls create_object generic view with a custom form class.
3827-    """
3828-    class SlugChangingArticleForm(forms.ModelForm):
3829-        """Custom form class to overwrite the slug."""
3830-
3831-        class Meta:
3832-            model = Article
3833-
3834-        def save(self, *args, **kwargs):
3835-            self.instance.slug = 'some-other-slug'
3836-            return super(SlugChangingArticleForm, self).save(*args, **kwargs)
3837-
3838-    from django.views.generic.create_update import create_object
3839-    return create_object(request,
3840-        post_save_redirect='/create_update/view/article/%(slug)s/',
3841-        form_class=SlugChangingArticleForm)
3842-
3843 def raises(request):
3844     # Make sure that a callable that raises an exception in the stack frame's
3845     # local vars won't hijack the technical 500 response. See:
3846--
38471.7.2.5
3848