template using old content upon rerender


I am trying to rerender my template with a different value on a POST request, the view is:

class Playground(TemplateView):
    template = "test/playground.html"
    context = {}

    def get(self, request):
        self.context = dict(test="ok")
        return render(request, self.template, self.context)

    def post(self, request):
        type_of = request.POST.get('type')
        if type_of == "view_change":
            self.context = dict(test=request.POST.get('to'))
            return HttpResponseRedirect(request.build_absolute_uri(), json.dumps(self.context), content_type="application/json")

And then in the template I have: <p>{{ test }}</p>, however the value of test stays as ok (and I have confirmed the POST request is successful). Note that the same effect happens if I use render or HttpResponse. I understand I can just set the value of the p tag in the ajax response, however then I am unsure what to do with more complicated templates such as:

    {% for choice in test %}
        <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
    {% endfor %}

- How would I properly set the value of test here for instance?

Thanks for any help!

Values for self will not be preserved across requests. And nor would you want them to be, since they’d be shared by visitors to your site.

It looks like you might want something like the messages framework to store something between requests? Or a database model?

Well, I’m not trying to preserve values for self, right? The only thing ‘saved’ is the context but I want to change that anyway (to the value of the POST). So even if I added a database model, which I probably should do in any case, the template is still not showing the correct visible value.

I think you’re misunderstanding both Python’s class model and how Django uses class based views.

  1. self.context = ... assigns to the instance only, not the class. If you instead mutated the dictionary, it would remain using the one on the class: self.context["key"] = "value"
  2. Django instantiates a new Playground per response
  3. Any class variables on Playground are shared amongst all requests on the same process. So two users looking at the page at the same time could see each others’ data.
  4. Conversely, they’re not shared between processes - which means when you deploy this, you might get an answer from server A with a redirect, then when you do the GET request it’s served by process B, where the modification to the class didn’t happen.

I suggest you try using function based views to begin with, they give you a clearer model of how Django answers a request.

Ah thanks for the tips, but I’m not trying to accomplish that, let me make it much simpler, sorry for the confusion! -

class Playground(TemplateView):
    template = "test/playground.html"

    def get(self, request):
        context = dict(test="ok")
        return render(request, self.template, context)

    def post(self, request):
        type_of = request.POST.get('type')
        if type_of == "view_change":
            context = dict(test=request.POST.get('to'))
            return HttpResponseRedirect(request.build_absolute_uri(), json.dumps(context), content_type="application/json")

Ok, so as you see I’m not actually trying to save stuff to the class, that’s an entirely different issue, but am I still running into one of the issues you have mentioned?