Are class instance variables constant?

I just started using class based views in django. But there is a problem that baffles me. I executed the following code snippet with django 1.4.1 with a multi-threaded development server.

class TestView(TemplateView): template_name = 'test.html' count = 0 mylist = [1, ] def get(self, request, *args, **kwargs): self.count += 1 self.mylist.append(self.mylist[-1] +1) context = self.get_context_data(**kwargs) return self.render_to_response(context) def get_context_data(self, **kwargs): context = super(TestView, self).get_context_data(**kwargs) context['count'] = self.count context['mylist'] = self.mylist return context 

The template only displays a count of context variables and mylist. When this view is called, for example. up to 5 times the output will look like this:

 count: 1 mylist: [1, 2, 3, 4, 5, ] 

And now I'm embarrassed. The django docs say that each request has its own instance of the class.

So how can I expand mylist across multiple queries? Why was the count variable not incremented?

+4
source share
3 answers

If you need something available across multiple requests, you need to add it to the session. Ivar is not for that. To ensure thread safety, the as_view method returns a new instance of the class every time that is not executed by anything else, which happens in other instances of the same class. This is by design, and you would have a lot of problems if it weren’t.

+1
source
Lists

are mutable. ints are immutable

You can add to the list, and this is still the same link to your class. But when you do self.count += 1 , each time you create a new int object, which becomes the scope of this instance. Value never affects the class.

If, for example, you configured it like this:

 count = [0] def get(self): self.count[0] += 1 

You will see that the score will increase between instances, because you change the member of the list and do not replace the object each time. Not that I recommend this container. Just an example.

You can specifically modify the class directly by doing something like this:

 count = 0 def get(self): self.__class__.count += 1 

This will replace the int object at the class level every time.

But I would be very careful trying to keep class data between threads like this. It is not thread safe. The problem with read-only data is not really a problem, but changing it from multiple threads can be problematic. It would be much better if you saved your data in a database.

0
source

In each request, a new view is created and called without knowing the previous view. To save some information across multiple views, you need to put it in a persistent repository, which in Django usually means any database if you need long-term repository, or sessions for short-term perseverance.

In addition, there is almost no need to override get (and post ); everything you did there can be done in the get_context_data method.

0
source

All Articles