views:

86

answers:

2

Hi there!

I'm searching in a way to limit the queryset which I can get through a model.

Suppose I have the following models (with dependencies):

Company
 |- Section
 |   |- Employee
 |   |- Task
 |   `- more models...
 |- Customer
 |   |- Contract
 |   |- Accounts
 |   `- other great models ...
 `- some more models...

It should be noted that my real models are much deeper and it's not really about business.

With a context processor I have added a company instance to request:

def magic_view(request):
    request.company # is a instance of Company model

Now my question is what is the best way to limit the access to the child models of Company to the request instance of company?

I could make it like task = Task.objects.get(pk=4,section__task=task), but this is a bad way if my model structure is getting deeper.

Edit: I could give each other model a foreign key to company, but is this a good practice to store relations redundant? Edit 2: No it isn't. See http://stackoverflow.com/questions/3347008/is-it-bad-to-use-redundant-relationships.

A: 

Treat your hierarchy as a graph. Let all your models extend the Node class:

class Node(models.Model):
parent = models.ForeignKey("Node", blah blah...)
def get_root(self):
    n = self
    while ((n = n.parent) != None): pass
    return n

Then you can limit your queryset like that:

qset = Task.objects.filter(blah...)
result = []
for row in qset:
    if row.get_root() == request.company:
        result += row

It's sloooowwww, but it's all I can come up to at 2:00 AM

joozek
Yes it *is* slow ;-)
Sven Walter
A: 

I solved it the following way:

First I've created a CurrentCompanyManager.

class CurrentCompanyManager(models.Manager):
    def __init__(self,field,*args,**kwargs):
        super(CurrentCompanyManager,self).__init__(*args,**kwargs)
        self.__field_name = field

    def on(self,company):
        return self.filter( **{  self.__field_name + '__id__exact':company.id } )

Than I added the manager to all models where I need it.

class Employee(models.Model):
    # some fields and relationships
    objects = CurrentCompanyManager("section__company")

class Accounts(models.Model):
    # some fields and relationships
    objects = CurrentCompanyManager("customer__company")

And now I can easily limit the model data in the view.

def magic_view(request):
    Employee.objects.on(request.company).all()

It should be self-explanatory. If not, then ask me.

Sven Walter