Filter based on result of model method
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
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
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
> 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
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
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
> 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
> 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.