Filter based on result of model method

2010-07-03 Thread Wiiboy
Is there a way to filter based on the result of a model instance
method?

I've got a Permission model with a one-to-one relationship with an
Article.  The Permission model stores the different groups that the
Article author said could read their article.  There's about 6 groups
though, so I wrote an instance method that calculates whether a given
user can view an Article.

I want to filter based on whether that instance method returns true or
not. I could do something like the following, but it seems very
inefficient.

def myview(request):
   q = Article.objects.all()
   for item in q:
   if not item.permission.can_view_article(request.user):
   q = q.exclude(item.pk)

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.



Re: Filter based on result of model method

2010-07-05 Thread Wiiboy
Anyone?

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.



Re: Filter based on result of model method

2010-07-05 Thread Mark Linsey
Perhaps someone with much more Django experience will correct me, but I am
99% sure that this is impossible.

As I understand it, parameters passed to filter() are translated into SQL
statements.  An arbitrary python method that you write for your object can
do any number of things, which might not be translatable into SQL.  So I
don't see how any "filter on the result of any method" feature would work,
other than doing exactly the implementation you describe.

However, your specific use case sounds like it should be possible to avoid
iterating over everything by changing your model.  Is there a reason why
each Permission model can't have a ManyToMany field with the set of users
allowed by that permission model?

On Mon, Jul 5, 2010 at 11:11 PM, Wiiboy  wrote:

> Anyone?
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To post to this group, send email to django-us...@googlegroups.com.
> To unsubscribe from this group, send email to
> django-users+unsubscr...@googlegroups.com
> .
> For more options, visit this group at
> http://groups.google.com/group/django-users?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.



Re: Filter based on result of model method

2010-07-06 Thread Wiiboy

> As I understand it, parameters passed to filter() are translated into SQL
> statements.  An arbitrary python method that you write for your object can
> do any number of things, which might not be translatable into SQL.  So I
> don't see how any "filter on the result of any method" feature would work,
> other than doing exactly the implementation you describe.

Curses, that's what I thought.

> However, your specific use case sounds like it should be possible to avoid
> iterating over everything by changing your model.  Is there a reason why
> each Permission model can't have a ManyToMany field with the set of users
> allowed by that permission model?

That'd be really hard to maintain,  I think.  I'd have to evaluate
whether the current user could view _every_ article every time they
changed their profile, registered, etc.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.



Re: Filter based on result of model method

2010-07-07 Thread euan.godd...@googlemail.com
As stated there is no way to filter on any non-field attribute,
property or method.

However, don't despair. If the result of your permission check can be
expressed as another Django query then it should be possible to
construct something in the ORM that uses this. That said, we have had
trouble with highly complex permissions and large querysets and have
had to come up with a permissions caching mechanism so that our site
doesn't do too many queries per page.

Good luck, Euan

On Jul 7, 1:47 am, Wiiboy  wrote:
> > As I understand it, parameters passed to filter() are translated into SQL
> > statements.  An arbitrary python method that you write for your object can
> > do any number of things, which might not be translatable into SQL.  So I
> > don't see how any "filter on the result of any method" feature would work,
> > other than doing exactly the implementation you describe.
>
> Curses, that's what I thought.
>
> > However, your specific use case sounds like it should be possible to avoid
> > iterating over everything by changing your model.  Is there a reason why
> > each Permission model can't have a ManyToMany field with the set of users
> > allowed by that permission model?
>
> That'd be really hard to maintain,  I think.  I'd have to evaluate
> whether the current user could view _every_ article every time they
> changed their profile, registered, etc.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.



Re: Filter based on result of model method

2010-07-07 Thread Matthias Kestenholz
On Sat, Jul 3, 2010 at 7:20 PM, Wiiboy  wrote:
> Is there a way to filter based on the result of a model instance
> method?
>
> I've got a Permission model with a one-to-one relationship with an
> Article.  The Permission model stores the different groups that the
> Article author said could read their article.  There's about 6 groups
> though, so I wrote an instance method that calculates whether a given
> user can view an Article.
>
> I want to filter based on whether that instance method returns true or
> not. I could do something like the following, but it seems very
> inefficient.
>

As other have already written, it's not possible to filter on the
result of a model method.

There's at least one thing you can do differently to speed up this method a bit.

> def myview(request):
>   q = Article.objects.all()
>   for item in q:
>       if not item.permission.can_view_article(request.user):
>           q = q.exclude(item.pk)
>

Everytime you call exclude (btw, this should be q =
q.exclude(pk=item.pk), no?), a new queryset instance is constructed.
This is probably not neccessary. You could do this instead, assuming
permission is another database model linked with a foreign key:

articles = [article for article in
Article.objects.all().select_related('permission') if
article.permission.can_view_article(request.user)]

At least you'll hit the article table only once this way.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.



Re: Filter based on result of model method

2010-07-07 Thread Wiiboy

> Everytime you call exclude (btw, this should be q =
> q.exclude(pk=item.pk), no?),

Yes =)  I wrote that quickly with my post.

> articles = [article for article in
> Article.objects.all().select_related('permission') if
> article.permission.can_view_article(request.user)]

Good idea.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.



Re: Filter based on result of model method

2010-07-07 Thread Wiiboy

> articles = [article for article in
> Article.objects.all().select_related('permission') if
> article.permission.can_view_article(request.user)]

The only problem I see is that is that 'articles' is a list, not a
queryset.  The reason I was using q.exclude(pk=item.pk) is because the
return value is still a queryset.  But that's going to result in a
huge number of DB hitscurses.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.