On 3/04/2012 7:00pm, Tom Evans wrote:
On Tue, Apr 3, 2012 at 9:43 AM, Mike Dewhirst<mi...@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+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to