summaryrefslogtreecommitdiff
path: root/docs/topics/generic-views-migration.txt
blob: fa62f5de1f584f276fc0fe8b68eee2a75bae2e92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
======================================
Migrating function-based generic views
======================================

All the :doc:`function-based generic views</ref/generic-views>`
that existed in Django 1.2 have analogs as :doc:`class-based generic
views</ref/class-based-views>` in Django 1.3. The feature set
exposed in those function-based views can be replicated in a
class-based way.

How to migrate
==============

Replace generic views with generic classes
------------------------------------------

Existing usage of function-based generic views should be replaced with
their class-based analogs:

    ====================================================  ====================================================
    Old function-based generic view                       New class-based generic view
    ====================================================  ====================================================
    ``django.views.generic.simple.direct_to_template``    :class:`django.views.generic.base.TemplateView`
    ``django.views.generic.simple.redirect_to``           :class:`django.views.generic.base.RedirectView`
    ``django.views.generic.list_detail.object_list``      :class:`django.views.generic.list.ListView`
    ``django.views.generic.list_detail.object_detail``    :class:`django.views.generic.detail.DetailView`
    ``django.views.generic.create_update.create_object``  :class:`django.views.generic.edit.CreateView`
    ``django.views.generic.create_update.update_object``  :class:`django.views.generic.edit.UpdateView`
    ``django.views.generic.create_update.delete_object``  :class:`django.views.generic.edit.DeleteView`
    ``django.views.generic.date_based.archive_index``     :class:`django.views.generic.dates.ArchiveIndexView`
    ``django.views.generic.date_based.archive_year``      :class:`django.views.generic.dates.YearArchiveView`
    ``django.views.generic.date_based.archive_month``     :class:`django.views.generic.dates.MonthArchiveView`
    ``django.views.generic.date_based.archive_week``      :class:`django.views.generic.dates.WeekArchiveView`
    ``django.views.generic.date_based.archive_day``       :class:`django.views.generic.dates.DayArchiveView`
    ``django.views.generic.date_based.archive_today``     :class:`django.views.generic.dates.TodayArchiveView`
    ``django.views.generic.date_based.object_detail``     :class:`django.views.generic.dates.DateDetailView`
    ====================================================  ====================================================

To do this, replace the reference to the generic view function with
a ``as_view()`` instantiation of the class-based view. For example,
the old-style ``direct_to_template`` pattern::

    ('^about/$', direct_to_template, {'template': 'about.html'})

can be replaced with an instance of
:class:`~django.views.generic.base.TemplateView`::

    ('^about/$', TemplateView.as_view(template_name='about.html'))

``template`` argument to ``direct_to_template`` views
-----------------------------------------------------

The ``template`` argument to the ``direct_to_template`` view has been renamed
``template_name``. This has been done to maintain consistency with other views.

``object_id`` argument to detail views
--------------------------------------

The object_id argument to the ``object_detail`` view has been renamed
``pk`` on the :class:`~django.views.generic.detail.DetailView`.

``template_object_name``
------------------------

``template_object_name`` has been renamed ``context_object_name``,
reflecting the fact that the context data can be used for purposes
other than template rendering (e.g., to populate JSON output).

The ``_list`` suffix on list views
----------------------------------

In a function-based :class:`ListView`, the ``template_object_name``
was appended with the suffix ``'_list'`` to yield the final context
variable name. In a class-based ``ListView``, the
``context_object_name`` is used verbatim. The ``'_list'`` suffix
is only applied when generating a default context object name.

The context data for ``object_list`` views
------------------------------------------

The context provided by :class:`~django.views.generic.list.MultipleObjectMixin`
is quite different from that provided by ``object_list``, with most pagination
related variables replaced by a single ``page_obj`` object. The following are no
longer provided:

* ``first_on_page``
* ``has_next``
* ``has_previous``
* ``hits``
* ``last_on_page``
* ``next``
* ``page_range``
* ``page``
* ``pages``
* ``previous``
* ``results_per_page``

``extra_context``
-----------------

Function-based generic views provided an ``extra_context`` argument
as way to insert extra items into the context at time of rendering.

Class-based views don't provide an ``extra_context`` argument.
Instead, you subclass the view, overriding :meth:`get_context_data()`.
For example::

    class MyListView(ListView):
        def get_context_data(self, **kwargs):
            context = super(MyListView, self).get_context_data(**kwargs)
            context.update({
                'foo': 42,
                'bar': 37
            })
            return context

``post_save_redirect`` argument to create and update views
----------------------------------------------------------

The ``post_save_redirect`` argument to the create and update views
has been renamed ``success_url`` on the
:class:`~django.views.generic.edit.ModelFormMixin`.

``mimetype``
------------

Some function-based generic views provided a ``mimetype`` argument
as way to control the mimetype of the response.

Class-based views don't provide a ``mimetype`` argument. Instead, you
subclass the view, overriding
:meth:`TemplateResponseMixin.render_to_response()` and pass in arguments for
the TemplateResponse constructor. For example::

    class MyListView(ListView):
        def render_to_response(self, context, **kwargs):
            return super(MyListView, self).render_to_response(context,
                            content_type='application/json', **kwargs)

``context_processors``
----------------------

Some function-based generic views provided a ``context_processors``
argument that could be used to force the use of specialized context
processors when rendering template content.

Class-based views don't provide a ``context_processors`` argument.
Instead, you subclass the view, overriding
:meth:`TemplateResponseMixin.render_to_response()`, and passing in
a context instance that has been instantiated with the processors
you want to use. For example::

    class MyListView(ListView):
        def render_to_response(self, context, **kwargs):
            return super(MyListView, self).render_to_response(
                    RequestContext(self.request,
                                   context,
                                   processors=[custom_processor]),
                    **kwargs)