[Fixed]-Class based generic views extra context

23👍

After too much thoughts, the only answer is NO, that functionality was removed.

And the documentation does not mention the “Removed feature” and there is no explanation why it was like this.

But for making my life easier I took the advice from @aidan and modified a little bit

class ExtraContext(object):
    extra_context = {}

    def get_context_data(self, **kwargs):
        context = super(ExtraContext, self).get_context_data(**kwargs)
        context.update(self.extra_context)
        return context

class ExtraListView(ExtraContext, ListView):
    pass

class ExtraDetailView(ExtraContext, DetailView):
    pass

class ExtraUpdateView(ExtraContext, UpdateView):
    pass

class ExtraCreateView(ExtraContext, CreateView):
    pass 

class ExtraDeleteView(ExtraContext, DeleteView):
    pass

class ExtraCloneView(ExtraUpdateView):
    def post(self, request, *args, **kwargs):
       return ExtraCreateView.as_view(model=self.model,
                              template_name=self.template_name,
                              extra_context=self.extra_context)(request, *args, **kwargs)    

Now I have semi-generic views that I can use directly in the URLSconf and pass extra_context dict to the as_view() call

url(r'^camera/(?P<pk>\d+)/$', 
    views.ExtraDetailView.as_view(model=models.Camera,
                               extra_context={'action_type': 'detail', 'mod_name' : 'camera'},
                               template_name='cameras/camera_detail.html'), 
    name='camera_detail'),
👤fariza

15👍

I guess it’s not quite so simple, but it’s still only 5 lines of code –

class MyView(CreateView):
    def get_context_data(self, *args, **kwargs):
        context = super(MyView, self).get_context_data(*args, **kwargs)
        context['my_additional_context'] = my_object
        return context

If you really want that functionality with class based views, then perhaps you could extend the class to add it –

class MyCreateView(CreateView)
    additional_context = {}
    def get_context_data(self, *args, **kwargs):
        context = super(MyView, self).get_context_data(*args, **kwargs)
        context.append(self.additional_context)
        return context

Then use it in your url_conf –

urlpatterns = patterns('',
    #....
    (r'^my_url/$', MyCreateView.as_view(additional_context={'my_addional_context': my_object})),
)

You could write your own CreateView, DetailView, ListView etc and import them into every project you do.

11👍

Reading the above answers, it seemed that this approach, while solving the problem, was essentially a hack to bring back old functionality. A little googling brought up the generic class-based views page, which contains a section titled “adding extra context.” Just to summarize here, the solution is simply to implement your own version of get_context_data() which would include the variables you want to pass to the templates:

from django.views.generic import DetailView
from books.models import Publisher, Book

class PublisherDetail(DetailView):

    model = Publisher

    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super(PublisherDetail, self).get_context_data(**kwargs)
        # Add in a QuerySet of all the books
        context['book_list'] = Book.objects.all()
        return context

The biggest benefit here is that you are not required to “hack” urls.py to include all sorts of context arguments, you can take advantage of all the functionality provided by class-based views while still providing custom-defined context content.

1👍

Just use extra_context, this was added back in 2017 (https://github.com/django/django/pull/8671)

0👍

With full credit to mogga’s comment to the accepted answer::

2.0 brought back extra_context docs.djangoproject.com/en/2.1/ref/class-based-views/… – mogga

So the way to get it is to upgrade to 2.X if you’re not on it already.

👤ic_fl2

Leave a comment