Re: #6735 -- Class based generic views: call for comment
I should add.. The bonus of using class-based decorators is that decorated views can be subclassed. All other functionality is retained. -- 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.
Re: #6735 -- Class based generic views: call for comment
On Oct 3, 1:02 pm, Russell Keith-Magee wrote: > On Sun, Oct 3, 2010 at 12:12 PM, Ian Lewis wrote: > > On Sun, Oct 3, 2010 at 11:20 AM, Russell Keith-Magee > > wrote: > > While I'm in the "one singleton view instance is best" camp and think > > that storing some state on the request and some on the view is a bit > > gross, I understand Russell's arguments. New users are simply going to > > save stuff on self no matter how much we complain, document etc. It's > > simply a reality that likely can't be helped much. > > > Other frameworks seem have View/Handler instances per request, such as > > appengine's webapp so there is some precedent for creating an instance > > per request. > > >http://code.google.com/appengine/docs/python/gettingstarted/handlingf... > > I don't think you'll find any argument that having an instance per > request would solve all the problems that this thread has described. > The issue is how to declare a view that is able to be instantiated on > a instance-per-request basis while simultaneously allowing decorators > to be easily wrapped around that view. > > Yours, > Russ Magee %-) I haven't investigated the other solutions described in this discussion, but the solution I proposed handles decorators just fine. Furthermore, you can extend it to allow for decorators by subclassing. Initial code: class BaseView(object): def __new__(cls, *args, **kwargs): obj = super(BaseView, cls).__new__(cls) # Call __init__ manually since it will not be called # after this method (since __new__ returns a HttpResponse # and not a BaseView subclass). obj.__init__(*args, **kwargs) return obj.view() # Or other name class MyView(BaseView): def __init__(self, request): self.request = request def view(self): return HttpResponse(self.request.path) urlpatterns = patterns("", ("^login_required_view/$", login_required(MyView))) This will create a view that requires login. We can extend this by introducing a helper function class_decorator that takes a regular decorator and turns it into a view class: def class_decorator(decorator): class Cls(BaseView): def __new__(cls, *args, **kwargs): def view(*args, **kwargs): return super(Cls, cls).__new__(cls, *args, **kwargs) return decorator(view)(*args, **kwargs) return Cls We can then create a LoginRequiredView for instance: LoginRequiredView = class_decorator(login_required) class MyView2(LoginRequiredView): def __init__(self, request): self.request = request def view(self): return HttpResponse(self.request.path) MyView2 functions like login_required(MyView). We can also chain decorators by multiple inheritance. AUsersView = class_decorator(user_passes_test(lambda u: "a" in u.username.lower())) class MyView3(LoginRequiredView, AUsersView): """ View that requires users to be logged in and have a username that contain an 'a'. """ def __init__(self, request): self.request = request def view(self): return HttpResponse(self.request.path) Best regards, André Eriksson -- 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.
Re: #6735 -- Class based generic views: call for comment
On Oct 3, 1:02 pm, Russell Keith-Magee wrote: > On Sun, Oct 3, 2010 at 12:12 PM, Ian Lewis wrote: > > On Sun, Oct 3, 2010 at 11:20 AM, Russell Keith-Magee > > wrote: > > While I'm in the "one singleton view instance is best" camp and think > > that storing some state on the request and some on the view is a bit > > gross, I understand Russell's arguments. New users are simply going to > > save stuff on self no matter how much we complain, document etc. It's > > simply a reality that likely can't be helped much. > > > Other frameworks seem have View/Handler instances per request, such as > > appengine's webapp so there is some precedent for creating an instance > > per request. > > >http://code.google.com/appengine/docs/python/gettingstarted/handlingf... > > I don't think you'll find any argument that having an instance per > request would solve all the problems that this thread has described. > The issue is how to declare a view that is able to be instantiated on > a instance-per-request basis while simultaneously allowing decorators > to be easily wrapped around that view. > > Yours, > Russ Magee %-) I haven't investigated the other solutions described in this discussion, but the solution I proposed handles decorators just fine. class BaseView(object): def __new__(cls, *args, **kwargs): obj = super(BaseView, cls).__new__(cls) # Call __init__ manually since it will not be called # after this method (since __new__ returns a HttpResponse # and not a BaseView subclass). obj.__init__(*args, **kwargs) return obj.view() # Or other name class MyView(BaseView): def __init__(self, request): self.request = request def view(self): return HttpResponse(self.request.path) urlpatterns = patterns("", ("^login_required_view/$", login_required(MyView))) Best regards, André Eriksson -- 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.
Re: #6735 -- Class based generic views: call for comment
On Oct 2, 12:32 pm, Russell Keith-Magee wrote: > > The difference is that __new__ doesn't *ever* allow for initialization > arguments -- there is no way to pass an argument in. An "arguments > disabled by default" __init__+copy implementation allows arguments as > an opt-in. > > There's also the wierd behavior that __new__ requires. Consider: > > x = MyView() > > What is x? If you use the __init__+copy approach, x is an instance of > MyView. If you use __new__, x is a HttpResponse. It's a minor thing, > to be sure, but this is a bit of a code smell to me. This to me seems logical. If MyView is the view, calling it should return a HttpResponse to me. If this little peculiarness can be gotten around, I think __new__ can be used to allow for quite an elegant solution if you ask me. While reading this thread arguments against this solution are that you either can't use decorators, or that you cannot pass in arguments to __init__. First of all, consider the following implementation: class BaseView(object): def __new__(cls, *args, **kwargs): obj = super(BaseView, cls).__new__(cls) # Call __init__ manually since it will not be called # after this method (since __new__ returns a HttpResponse # and not a BaseView subclass). obj.__init__(*args, **kwargs) return obj.view() # Or other name class MyView(BaseView): def __init__(self, request): self.request = request def view(self): return HttpResponse(self.request.path) The first argument, that you cannot use decorators, is not true. Wrapping MyView in login_required() works just fine. The second argument, that you cannot pass in initialization arguments, I'm not sure about. It can either be interpreted as "__init__ is not called with the view arguments like other views", to which I demonstrated above that it indeed is. If it is to be interpreted as "you cannot customize your view by calling __init__ with different arguments for each view consisting of the same class", then yes, that's true. However, I don't think that's a big problem since the main focus is on subclassing as customization. It's also not a feature present in regular, function-based views, and is mainly gotten around by decorators (which work just fine with the method above). Forgive me if the solution above has some flaws I can't see that have already brought up, but to me it seems to have some good qualities. Best regards, André Eriksson -- 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.
Re: Proposal: Revised form rendering
It appears my reply got eaten so I'm trying again. On Jul 12, 3:43 pm, Russell Keith-Magee wrote: > I'm having difficulty reconciling these two positions. My template tag > is too complex because it requires you to remember the idiom FORM X > FIELD Y USING Z; but a nested tag structure with 4 different subtags > is more readable and won't require reference to documentation to > understand how and when to use each subtag? My biggest issue with using {% form myform field A %} to render a single field is the non-DRY-ness of it all, especially if you have a semi-large form. The issue being that if one field has its chrome changed, all the other fields must be hand-defined as well. Example: {% form myform field A using X Y %} {% form myform field B %} {% form myform field C %} {% form myform field D %} {% form myform field E %} ... My proposition was to let the {% form myform %}{% endform %} block tag render the whole form if desired, akin to how {{ myform }} works today. In this scenario, {% using %} would override the chrome of the field without affecting its order in the form. As such, the above becomes: {% form myform %} {% using A = X Y %} {# Or some other syntax #} {% endform %} Perhaps this wasn't clear enough from my original proposition. -- 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.
Re: Proposal: Revised form rendering
On Jul 12, 3:43 pm, Russell Keith-Magee wrote: > > Andre's idea is interesting and is certainly more readable. > > I'm having difficulty reconciling these two positions. My template tag > is too complex because it requires you to remember the idiom FORM X > FIELD Y USING Z; but a nested tag structure with 4 different subtags > is more readable and won't require reference to documentation to > understand how and when to use each subtag? I think the other approach lends itself to a lot of non-DRY. For example, if you want to define the chrome of a single field you end up having to define *every single field* along with it. Example: {% form myform field A using X Z %} {% form myform field B %} {% form myform field C %} {% form myform field D %} {% form myform field E %} My idea with the form block tag was to allow a way to replace the chrome of a single field without having to define all the other fields. In other words, the above would just be: {% form myform %} {% using A = X Z %} {# Or whatever syntax looks good %} {% endform %} And the form would be rendered as {{ myform }} would, except with the chrome of the field A being replaced with X and Z. Perhaps this wasn't clear from my proposition. -- 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.
Re: Proposal: Revised form rendering
On Jul 12, 5:27 am, Javier Guerra Giraldez wrote: > > 1) It introduces a clearer way of laying out settings. > > 2) It leverages the template engine for specifying defaults in a > > simple but ingenious way: > > {% form myform %} > > {% include "form_settings.django" %} > > {% endform %} > > -- form_settings.django: > > {% doctype xhtml1 %} > > {% replace_widget datetime=calendar %} > > personally, i don't think this is a nice solution. {%include%}'ing a > set of settings is not a default, it's a packaged setting. My idea was merely to provide a very flexible way for template authors to define a single point of form settings if they so choose, without introducing yet another way of defining settings and figuring out a way to make it flexible enough to handle the various use cases. As Russ pointed out, sometimes doctypes aren't sitewide, whereas other times they are. By allowing (but not requiring!) the inherent flexibility of django's template system in the form settings, the template authors and by extension the designers are put in control of how forms are rendered and to what extent default settings should be provided and to what magnitude they affect the site. André -- 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.
Re: Proposal: Revised form rendering
Good proposal overall. One thought I have in order to try and combat the massive parameter list of {% form %} is to optionally add an ending tag, as well as sub-tags: {% form myform %} {% using birthday=calendar %} {% renderer "as_ul" %} {% autocomplete "name_autocomplete" %} {% doctype xhtml1 %} {% endform %} I see this as having several advantages: 1) It introduces a clearer way of laying out settings. 2) It leverages the template engine for specifying defaults in a simple but ingenious way: {% form myform %} {% include "form_settings.django" %} {% endform %} -- form_settings.django: {% doctype xhtml1 %} {% replace_widget datetime=calendar %} And because of the flexibility of the template engine we can easily specify either section-, site- or project-specific form settings, with the use of block tags and overriding them. This can be accomplished in a few ways: 1) Keeping the current {{ myform }} method for displaying forms without settings attached. 2) Converting to always using {% form myform %}, where the {% form %} tag parses until it either finds a matching {% endform %} tag or a new {% form %} tag; a new {% form %} tag means that there are no settings attached. 3) Adding a parameter to {% form %} for settings: {% form myform detailed %} {# settings #} {% endform %} 4) Adding two template tags, one for simple form rendering, another for detailed form rendering. Naming them is left as an exercise to the reader. -- 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.
Re: Custom FilterSpecs #5833 planned for Django 1.1?
On Feb 10, 5:43 am, Malcolm Tredinnick wrote: > Ignoring portions of a URL sounds pretty broken. Our goal isn't to be > like other frameworks. It's to behave correctly, in accordance with best > practices for things like URL construction and consumption. I would be a > little unhappy with 'ignoring' being something that happened there. I have attached a new patch (http://code.djangoproject.com/attachment/ ticket/5833/5833-against-9836-new-proper.patch) to attempt to address these issues. Is the approach taken acceptable? I believe the patch still needs tests, which I will get to as soon as I can. However, it would be nice to get some feedback on the quality of the patch before proceeding further. André --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@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 -~--~~~~--~~--~--~---