Re: custom manager to control access
On 3/04/2012 7:00pm, Tom Evans wrote:
> On Tue, Apr 3, 2012 at 9:43 AM, Mike Dewhirst<miked@dewhirst.com.au> wrote:
>> I'm trying to make a custom manager for a few models. The objective is to
>> limit user access to information in the database belonging to the company of
>> which they are a member.
>>
>> I think I want to say:
>>
>> class Something(models.Model):
>> ...
>> objects = MemberManager()
>>
>> But when I run manage.py runserver I get:
>>
>> AttributeError: 'MemberManager' object has no attribute '_inherited'
>>
>> Here is the code:
>>
>> from django.db import models
>> from company.models import *
>>
>> class MemberManager(models.Manager):
>> """
>> The manager in every model using this manager must return ONLY
>> rows belonging to the User's company. company.models.Member is
>> the table which links a member (ie user) to a particular company
>> in company.models.Company. Each member can be connected to exactly
>> zero or one company. If zero raise BusinessRuleViolation exception
>> otherwise return the company with which to filter query sets using
>> the user's company.
>> """
>> def __init__(self, request=None):
>> self.user = None
>> if request and request.user and request.user.is_authenticated():
>> self.user = request.user
>>
>> def get_company(self):
>> if self.user:
>> user_row = Member.objects.get(user=self.user)
>> return user_row.company
>>
>> def get_query_set(self):
>> coy = self.get_company()
>> if coy:
>> return super(MemberManager,
>> self).get_query_set().filter(company=coy)
>> raise BusinessRuleViolation('User must be a company Member')
>>
>>
>> From the research I've done it seems I should not have the __init__() in
>> this and indeed if I experimentally factor it out it the error goes away.
>>
>> The doc string says what I'm trying to do but maybe there is a better way
>> than a custom manager.
>>
>> Thanks for any pointers
>>
>> Mike
>>
> Two things:
>
> 1) You get the exception because you do not call the parent class's
> constructor, and thus the manager instance is not set up with the
> appropriate values. Your __init__() method on a derived class should
> look more like this:
>
> def __init__(self, *args, **kwargs):
> super(self, MyClassName).__init__(*args, **kwargs)
> # your stuff
>
> 2) Managers are not instantiated with the current request object, so
> your approach will not work anyway. You could use something like
> thread locals, but that is a hack (and won't work if/when you run
> outside of the request/response cycle).
I have now discarded the idea :)
I'm not very comfortable with thread locals. I need a bullet-proof
approach which makes data from other companies invisible to members of
this company. I suppose a view decorator is the way to go but I would
have preferred a deeper model-level approach.
Thanks
Mike
>
> Cheers
>
> Tom
>
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home