Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

class based generic views extra context

Tags:

django

Before class based views there was an extra_context keyword that can be passed in urlsconf. https://docs.djangoproject.com/en/1.3/topics/generic-views/#adding-extra-context

Now with class based generic views, if we want to do the same we have to subclass the generic view https://docs.djangoproject.com/en/1.3/topics/class-based-views/#adding-extra-context

If we want something simple, and we are using the generic CreateView and UpdateView. This approach will force to subclass for something that before was trivial. Even more, we have to break the DRY principle, doing it twice.

Why is it like this? Is there any reason why we can not pass the extra context directly to the template?

Thanks

like image 288
fariza Avatar asked Feb 11 '13 17:02

fariza


2 Answers

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'),
like image 100
fariza Avatar answered Sep 20 '22 10:09

fariza


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.

like image 44
Aidan Ewen Avatar answered Sep 24 '22 10:09

Aidan Ewen