On 05/23/2011 11:31 AM, Luke Plant wrote: > I think your core idea is quite interesting. I haven't had time to think > through all the implications. > > It does make the result of what is returned from view functions rather > obscure, and this could affect things like testing.
I don't think it's any more obscure - an HttpResponse is still an HttpResponse - just different. It changes the semantics of decorator_from_middleware so you can't expect the middlewares to be applied immediately without further response handling (more like actual middleware). > For example, the new tests I wrote for decorator_from_middleware, which > pass with my first patch on #16004, will not pass with this > implementation. This means the semantics are quite difference. It also > means that tests using RequestFactory could be broken, because they > won't pass through the machinery of request handling. Yes, the semantics would be different, and this would break some current tests that assume the current semantic of immediate application as part of the view function call. The entire issue, though, is that the current semantic of decorator_from_middleware is broken, because middlewares can't reliably be converted into something that runs immediately rather than in the middleware phase, and still work properly. One other option, I suppose, would be to introduce this as a new function, delayed_decorator_from_middleware, and convert cache_page and the csrf stuff to use it, to un-break them, without changing the current behavior of decorator_from_middleware. > However, with one modification, we can get something quite a bit better. > Basically, if it is a TemplateResponse, we defer the process_response > handling as you say. Otherwise, we do it the way we currently do it. > > In fact, we *almost* have machinery in place to do this - > 'TemplateResponse.add_post_render_callback' - and I've got a patch based > on that which works. The only problem is that currently > 'process_response' is allowed to return a completely new response > object, whereas that is not supported with add_post_render_callback. > > That would be easy to change, however - or we could add a similar hook > which does support it. Either way, it would require changing code like this: > > response.render() > > to > > response = response.render() > > This way, the only change people have to cope with in tests is adding > 'response = response.render()' to things that have 'render', rather than > having to invoke some other machinery to get the expected result - > TemplateResponse has all the machinery itself. Since they already have > to invoke 'render' for anything that has changed to TemplateResponse, > this change adds no extra burden. > > (BTW, we do need to document the change introduced by [16087] in the 1.4 > release notes as a breaking change - any tests against customized admin > views that use RequestFactory will currently break if they don't add > '.render()' calls.) > > Putting all these things together, I've uploaded a new patch to #16004: > > http://code.djangoproject.com/attachment/ticket/16004/16004.fix.alternative.diff > > It is not nearly as invasive as the other changes you suggested. > However, it does fix the failing tests in my project (i.e. fixes > csrf_protect), and leaves TemplateResponse objects unrendered as long as > possible, without having to change one line of my own code/tests. And > the implementation doesn't make me puke either. > > I agree that we ought to be doing something about middleware ordering > and things like that, but perhaps that is something for Django 2000 - > when we can sit down and work out how everything should fit together. This does seem like a relatively nice solution for TemplateResponse and decorator_from_middleware. Isn't the patch missing a modification to BaseHandler to do "response = response.render()" rather than just "response.render()"? Unfortunately, this doesn't do anything for the problem with cache_page and Vary headers, which isn't related to TemplateResponse. I'm not sure we can wait for Django 2000 to find a fix for that. > One little note while I remember - I'm really not happy about decorator > functions looking at settings to see how they should work - this is > fixing fragility by adding more fragility. We want to be getting rid of > this kind of thing, not adding more of it. I agree, of course. I only proposed that as a temporary deprecation-path check, not a permanent behavior. There was also the general > assumption of just one view being involved, one response object. We > don't want to break code that is slightly more inventive, like this: > > http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#view-needs-protection-for-one-path I don't like seeing that recommended in the documentation. For one thing, it's highly dependent on detailed knowledge of the implementation of csrf_protect and csrf_exempt. The response is still going to pass through both of those decorators; a naive reader would be as likely to assume "last-one-wins" as anything else. And I find it quite hard to read, compared to just having a function available that takes the request as argument and performs the CSRF check directly and immediately. > (Sorry for vague criticisms, I don't have more time to spend on this today). No problem, critiques appreciated. And - nor do I ;-) Carl -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
