On Fri, 2010-10-01 at 12:16 +0200, Johannes Dollinger wrote: > Am 01.10.2010 um 07:26 schrieb Russell Keith-Magee: > > I've just added a summary of the last thread on class-based views > [1]. > > This summary isn't 100% complete -- any contributions from > interested > > parties are welcome. Try to keep opinions to a minimum; this page is > > about documenting the strengths and weaknesses of various > approaches, > > not about expressing opinions. In the same way that CSRF [2] and > > session-messages [3] have good wiki pages describing the design > > considerations, we need to be able to explain to future generations > > why class-based views are the way they are. > > Could you (or anyone knowledgable) add a section, that explains why > each request should have its own view instance? > The thread-safety argument alone does not suffice: if all _request_ > state would be stored on request instead of the view, you wouldn't > need new instances per request. You could also pass around state > explicitly - which admittedly gets messy quickly. > So is this purely about preventing users from shooting themselves in > the foot? (hyperbole: Will there be protection from globals in django > 1.4?)
It's not just about stopping users from shooting themselves in the foot, it's about helping them to do the right thing easily. Without this kind of protection, it will be harder for *anyone*, including experienced developers who are aware of the problem, to do things correctly. It's like the autoescaping in templates - I *know* that I should use the 'escape' filter, but without autoescaping it is hard for anyone to do it right all the time. One alternative that has been suggested is to pass state around explicitly, which is definitely best practice, but in many cases might not be possible (e.g. if you are working with someone else's base class, and in one overridden method you want to set up some objects which ought to be available to other methods). You could also attach stateful data to the request object, but attaching random bits of data to the request is surely just as ugly a solution as the self.copy() call, especially if you need to avoid names clashes with all the other attributes attached to request. With regards to doing a shallow copy, it should be noted that at the point the copy is made, the only data attached to the object is data that has been attached in the constructor. It is of course possible that methods within the view might mutate such data, but it seems more likely that it will be used as immutable configuration data. However, I have already seen some example code that might fall foul of this problem - someone gave the example of storing a queryset on the object in the __init__. This will get implicitly mutated (the cache is filled) when it is used the first time. This could lead to frustrating problems that wouldn't be found in testing, and doing copy() on the instance won't help. So, in light of the fact that developers *will* need to be aware of this issue, I'd like to tentatively suggest an explicit solution which is nonetheless easy to use and get right. We could have an explicit 'state' object that is thrown away for every new request, something like this: class State(object): pass class View(object): def __call__(self, request, *args, **kwargs): """ Main entry point for a request-response process. """ self.state = State() self.request = request self.args = args self.kwargs = kwargs resp = self.dispatch(request, *args, **kwargs) # let any state get GC'd immediately: del self.state del self.request del self.args del self.kwargs return resp We document the issue, warn people not to store state on the instance itself, but tell them that if they must have stateful data, it should be attached to self.state instead of self, and they will be OK. They might still be bitten if they put mutable configuration data into the __init__ and it gets mutated, but we have made it easy to do the right thing - doing 'self.state.x' is only slightly harder than 'self.x' Thoughts? Luke -- "Despair: It's always darkest just before it goes pitch black." (despair.com) Luke Plant || http://lukeplant.me.uk/ -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.