Re: #6735 -- Class based generic views: call for comment

2010-10-03 Thread André Eriksson
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

2010-10-03 Thread André Eriksson


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

2010-10-03 Thread André Eriksson

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

2010-10-02 Thread André Eriksson


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

2010-07-12 Thread André Eriksson
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

2010-07-12 Thread André Eriksson
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

2010-07-11 Thread André Eriksson
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

2010-07-11 Thread André Eriksson
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?

2009-02-16 Thread André Eriksson

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
-~--~~~~--~~--~--~---