27

If I have a class based view, like this,

class SomeView (View):
    response_template='some_template.html'
    var1 = 0
    var2 = 1

    def get(self, request, *args, **kwargs):
        return render_to_response(self.response_template, locals(), context_instance=RequestContext(request))

My question is, inside the template some_template.html, how do I access var1 and var2? As far as I understood this, the locals() sort of just dumps all the local variables into the template, which has worked very well so far. But these other variables aren't technically "local", they're part of a class, so how do I pass them over??

Thanks!

5 Answers 5

44

A cleaner way of doing this could be to replicate Django's Template view:

class TemplateView(TemplateResponseMixin, ContextMixin, View):
    """
    A view that renders a template.  This view will also pass into the context
    any keyword arguments passed by the url conf.
    """
    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)

and then adding it to the get_context_data function. Or you could simply use the TemplateView which will allow you to specify a template name and then you could override the get_context_data function:

class SomeView(generic.TemplateView):
    var1 = 0
    var2 = 1 
    template_name = 'some_template.html'

    def get_context_data(self, **kwargs):
        context = super(SomeView, self).get_context_data(**kwargs)
        context.update({'var1': self.var1, 'var2': self.var2})
        return context

EDIT

Django has generic views which you can use for a variety of things, I would strongly advise you to go look at the docs for a full list of them, These generic views have functions you can override to do custom things which aren't supported by default. In your case you just wanted a template with context variables on them which means you subclass the TemplateView and supply the template_name and then finally you can override the get_context_data function to add your context data and that would be all there is to it, the second piece of code would be all you need in your case.

Sign up to request clarification or add additional context in comments.

2 Comments

I'm sure what you've written is a good solution, but I don't quite understand it... there are too many things in Django that I just don't get quite yet. This framework is a bit complex
I have updated my answer just to point you in the right direction for future use :)
22

Add self.var1 and self.var2 to the context in get method:

class SomeView (View):
    response_template='some_template.html'
    var1 = 0
    var2 = 1

    def get(self, request, *args, **kwargs):
        context = locals()
        context['var1'] = self.var1
        context['var2'] = self.var2
        return render_to_response(self.response_template, context, context_instance=RequestContext(request))

Note: render_to_response() is removed in Django 3.0 and above (use render() instead).

Also, I'm not sure that passing locals() as a context to the template is a good practice. I prefer to construct the data passed into the template explicitly = pass only what you really need in the template.

4 Comments

Is it because locals() could include a lot of random stuff that could pollute the namespace in the template? Introduce a whole bunch of stuff that I'll never use? Or is it for some other reason? Security ??
As Zen of Python says: Explicit is better than implicit. And it's just cleaner to look at and debug I think.
I agree that the use of locals() is bad practice. You can be explicit, just do so using the get_context_data() override -- in class-based views, that's considered the standard way to pass variables to the template.
render_to_response() is removed in Django 3.0. You should use render() if you are using Django 3.0 or more.
6

Update: As @max pointed in the comments, this solution doesn't work for Django 4.x.

There are two approaches as you can see here. The first one, you can declare a function named get_context_data like this:

def get_context_data(self, **kwargs):          
    context = super().get_context_data(**kwargs)                     
    new_context_entry = "here it goes"
    context["new_context_entry"] = new_context_entry
    return context

If you are using Django 2.x you must pass *args in get_context_data too.

The second approach is modifying extra_context variable in some function in the view:

self.extra_context["another_one"] = "here goes more"

1 Comment

This does not work on Django 4. There is no extra_context in View base class.
0

For passing your class label variable inside a function, you need to refer with self which refer as a newly created object. As we know for accessing any variable in class we need to refer to its object. Otherwise, it will be caught global name 'your variable' is not defined

as an example in your case you can do it like

class YourView(genericView):
    template_name='your_template.html'
    var1 = 12
    var2 =1

    def get(self, **kwargs):
        context = locals()
        context['var1'] = self.var1
       context['var2'] = self.var2
       return context

Comments

0

Here is the latest solution that works on Django 4:

class Account(View):
    login_required = True
    template_name = 'account.html'
    def get(self, request, *args, **kwargs):
        return render(request, self.template_name, {"username": request.user.first_name})

Here is the official documentation: https://docs.djangoproject.com/en/4.2/topics/class-based-views/intro/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.