Code

Ticket #18033: 18033-2.diff

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

Patch including docs

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