Ticket #16074: 16074-1.diff

File 16074-1.diff, 10.5 KB (added by Claude Paroz, 12 years ago)

Pull request + minor changes

  • django/views/generic/base.py

    diff --git a/django/views/generic/base.py b/django/views/generic/base.py
    index fcdc7c7..431cb1e 100644
    a b from django.utils.decorators import classonlymethod  
    88logger = getLogger('django.request')
    99
    1010
     11class ContextMixin(object):
     12    """
     13    A default context mixin that passes the keyword arguments received by
     14    get_context_data as the template context.
     15    """
     16
     17    def get_context_data(self, **kwargs):
     18        return kwargs
     19
     20
    1121class View(object):
    1222    """
    1323    Intentionally simple parent class for all views. Only implements
    class TemplateResponseMixin(object):  
    110120            return [self.template_name]
    111121
    112122
    113 class TemplateView(TemplateResponseMixin, View):
     123class TemplateView(TemplateResponseMixin, ContextMixin, View):
    114124    """
    115     A view that renders a template.
     125    A view that renders a template.  This view is different from all the others
     126    insofar as it also passes ``kwargs`` as ``params`` to the template context
     127    (this functionality has been deprecated).
    116128    """
    117129    def get_context_data(self, **kwargs):
    118         return {
    119             'params': kwargs
    120         }
     130        return super(TemplateView, self).get_context_data(**kwargs)
    121131
    122132    def get(self, request, *args, **kwargs):
    123         context = self.get_context_data(**kwargs)
     133        context = self.get_context_data(params=kwargs)
    124134        return self.render_to_response(context)
    125135
    126136
  • django/views/generic/dates.py

    diff --git a/django/views/generic/dates.py b/django/views/generic/dates.py
    index 5f5f959..e5c3e5b 100644
    a b class BaseDateListView(MultipleObjectMixin, DateMixin, View):  
    217217
    218218        return date_list
    219219
    220     def get_context_data(self, **kwargs):
    221         """
    222         Get the context. Must return a Context (or subclass) instance.
    223         """
    224         items = kwargs.pop('object_list')
    225         context = super(BaseDateListView, self).get_context_data(object_list=items)
    226         context.update(kwargs)
    227         return context
    228 
    229 
    230220class BaseArchiveIndexView(BaseDateListView):
    231221    """
    232222    Base class for archives of date-based items.
  • django/views/generic/detail.py

    diff --git a/django/views/generic/detail.py b/django/views/generic/detail.py
    index b9278bb..a2adb15 100644
    a b from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist  
    22from django.http import Http404
    33from django.utils.encoding import smart_str
    44from django.utils.translation import ugettext as _
    5 from django.views.generic.base import TemplateResponseMixin, View
     5from django.views.generic.base import TemplateResponseMixin, ContextMixin, View
    66
    77
    8 class SingleObjectMixin(object):
     8class SingleObjectMixin(ContextMixin):
    99    """
    1010    Provides the ability to retrieve a single object for further manipulation.
    1111    """
    class SingleObjectMixin(object):  
    8686            return None
    8787
    8888    def get_context_data(self, **kwargs):
    89         context = kwargs
     89        context = {}
    9090        context_object_name = self.get_context_object_name(self.object)
    9191        if context_object_name:
    9292            context[context_object_name] = self.object
    93         return context
     93        context.update(kwargs)
     94        return super(SingleObjectMixin, self).get_context_data(**context)
    9495
    9596
    9697class BaseDetailView(SingleObjectMixin, View):
  • django/views/generic/edit.py

    diff --git a/django/views/generic/edit.py b/django/views/generic/edit.py
    index d107e9a..1f488cb 100644
    a b  
    11from django.forms import models as model_forms
    22from django.core.exceptions import ImproperlyConfigured
    33from django.http import HttpResponseRedirect
    4 from django.views.generic.base import TemplateResponseMixin, View
     4from django.views.generic.base import TemplateResponseMixin, ContextMixin, View
    55from django.views.generic.detail import (SingleObjectMixin,
    66                        SingleObjectTemplateResponseMixin, BaseDetailView)
    77
    88
    9 class FormMixin(object):
     9class FormMixin(ContextMixin):
    1010    """
    1111    A mixin that provides a way to show and handle a form in a request.
    1212    """
    class FormMixin(object):  
    4545            })
    4646        return kwargs
    4747
    48     def get_context_data(self, **kwargs):
    49         return kwargs
    50 
    5148    def get_success_url(self):
    5249        if self.success_url:
    5350            url = self.success_url
    class ModelFormMixin(FormMixin, SingleObjectMixin):  
    113110        return super(ModelFormMixin, self).form_valid(form)
    114111
    115112    def get_context_data(self, **kwargs):
    116         context = kwargs
     113        context = {}
    117114        if self.object:
    118115            context['object'] = self.object
    119116            context_object_name = self.get_context_object_name(self.object)
    120117            if context_object_name:
    121118                context[context_object_name] = self.object
    122         return context
     119        context.update(kwargs)
     120        return super(ModelFormMixin, self).get_context_data(**context)
    123121
    124122
    125123class ProcessFormView(View):
  • django/views/generic/list.py

    diff --git a/django/views/generic/list.py b/django/views/generic/list.py
    index 9797356..d4664c3 100644
    a b from django.core.exceptions import ImproperlyConfigured  
    33from django.http import Http404
    44from django.utils.encoding import smart_str
    55from django.utils.translation import ugettext as _
    6 from django.views.generic.base import TemplateResponseMixin, View
     6from django.views.generic.base import TemplateResponseMixin, ContextMixin, View
    77
    88
    9 class MultipleObjectMixin(object):
     9class MultipleObjectMixin(ContextMixin):
    1010    allow_empty = True
    1111    queryset = None
    1212    model = None
    class MultipleObjectMixin(object):  
    103103                'is_paginated': False,
    104104                'object_list': queryset
    105105            }
    106         context.update(kwargs)
    107106        if context_object_name is not None:
    108107            context[context_object_name] = queryset
    109         return context
     108        context.update(kwargs)
     109        return super(MultipleObjectMixin, self).get_context_data(**context)
    110110
    111111
    112112class BaseListView(MultipleObjectMixin, View):
  • docs/topics/class-based-views.txt

    diff --git a/docs/topics/class-based-views.txt b/docs/topics/class-based-views.txt
    index 8059ed1..e1e2618 100644
    a b more::  
    270270            context['book_list'] = Book.objects.all()
    271271            return context
    272272
     273.. note::
     274
     275    Generally, get_context_data will merge the context data of all parent classes
     276    with those of the current class.  To preserve this behavior in your own classes
     277    where you want to alter the context, you should be sure to call
     278    get_context_data on the super class. When no two classes try to define the same
     279    key, this will give the expected results. However if any class attempts to
     280    override a key after parent classes have set it (after the call to super), any
     281    children of that class will also need to explictly set it after super if they
     282    want to be sure to override all parents.
    273283
    274284Viewing subsets of objects
    275285--------------------------
  • tests/regressiontests/generic_views/base.py

    diff --git a/tests/regressiontests/generic_views/base.py b/tests/regressiontests/generic_views/base.py
    index 6528dc6..e18ed2a 100644
    a b  
     1from __future__ import absolute_import
     2
    13import time
    24
    35from django.core.exceptions import ImproperlyConfigured
    from django.test import TestCase, RequestFactory  
    68from django.utils import unittest
    79from django.views.generic import View, TemplateView, RedirectView
    810
     11from . import views
    912
    1013class SimpleView(View):
    1114    """
    class RedirectViewTest(unittest.TestCase):  
    331334        # we can't use self.rf.get because it always sets QUERY_STRING
    332335        response = RedirectView.as_view(url='/bar/')(self.rf.request(PATH_INFO='/foo/'))
    333336        self.assertEqual(response.status_code, 301)
     337
     338
     339class GetContextDataTest(unittest.TestCase):
     340
     341    def test_get_context_data_super(self):
     342        test_view = views.CustomContextView()
     343        context = test_view.get_context_data(kwarg_test='kwarg_value')
     344
     345        # the test_name key is inserted by the test classes parent
     346        self.assertTrue('test_name' in context)
     347        self.assertEqual(context['kwarg_test'], 'kwarg_value')
     348        self.assertEqual(context['custom_key'], 'custom_value')
     349
     350        # test that kwarg overrides values assigned higher up
     351        context = test_view.get_context_data(test_name='test_value')
     352        self.assertEqual(context['test_name'], 'test_value')
  • tests/regressiontests/generic_views/tests.py

    diff --git a/tests/regressiontests/generic_views/tests.py b/tests/regressiontests/generic_views/tests.py
    index 72aab03..c985ad3 100644
    a b  
    11from __future__ import absolute_import
    22
    3 from .base import ViewTest, TemplateViewTest, RedirectViewTest
     3from .base import (ViewTest, TemplateViewTest, RedirectViewTest,
     4    GetContextDataTest)
    45from .dates import (ArchiveIndexViewTests, YearArchiveViewTests,
    56    MonthArchiveViewTests, WeekArchiveViewTests, DayArchiveViewTests,
    67    DateDetailViewTests)
  • tests/regressiontests/generic_views/views.py

    diff --git a/tests/regressiontests/generic_views/views.py b/tests/regressiontests/generic_views/views.py
    index 5ff9cf0..1e70ba4 100644
    a b class CustomTemplateView(generic.TemplateView):  
    1414    template_name = 'generic_views/about.html'
    1515
    1616    def get_context_data(self, **kwargs):
    17         return {
    18             'params': kwargs,
    19             'key': 'value'
    20         }
     17        context = super(CustomTemplateView, self).get_context_data(**kwargs)
     18        context.update({'key': 'value'})
     19        return context
    2120
    2221
    2322class ObjectDetail(generic.DetailView):
    class BookDetailGetObjectCustomQueryset(BookDetail):  
    184183    def get_object(self, queryset=None):
    185184        return super(BookDetailGetObjectCustomQueryset,self).get_object(
    186185            queryset=Book.objects.filter(pk=2))
     186
     187class CustomContextView(generic.detail.SingleObjectMixin, generic.View):
     188    model = Book
     189    object = Book(name='dummy')
     190
     191    def get_object(self):
     192        return Book(name="dummy")
     193
     194    def get_context_data(self, **kwargs):
     195        context = {'custom_key': 'custom_value'}
     196        context.update(kwargs)
     197        return super(CustomContextView, self).get_context_data(**context)
     198
     199    def get_context_object_name(self, obj):
     200        return "test_name"
Back to Top