views:

38

answers:

3

i have a small application i am implementing with django and i'm having a slight challenge. I'm trying to limit the queryset for my relationships within my application by a particular property. Now the catch is, the exact value of the property isn't known until the user logs into the application. an example is limiting a set of comments by a user's particular company, and the company is only determined when the user logs in. I don't know how to find my current session outside a django view. Any help is appreciated. Thanks

Here is a sample of a model from my application

class Tax(commons.models.EntityBase):
    name = models.CharField(blank=False, max_length=150)
    percentage_value = models.DecimalField(max_digits=4, decimal_places=2)
    notes = models.TextField(blank=True, null=True)
    auto_apply = models.NullBooleanField()
    aggregated_tax = models.NullBooleanField()

    def __unicode__(self):
        return self.name

Every entity inherits from the abstract class EntityBase, which holds the property company. I want to filter every query from the query manager such that they only return entities who's company are equal to the company in the session.

+1  A: 

It is perfectly ok to pass your session property, user or company or whatnot, to other functions in different parts of your system.

For example:

def view(request):
    user = request.user
    filtered_stuff = my_filter_function(..., user = user)

The my_filter_function may filter on the argument or may pass on the argument to other functions.

knutin
A: 

The best way that I've found to do this is using a custom QuerySet and Manager for your model. The accepted answer to this question, should get you started with this part. In your QuerySet, you can set up a method (I prefer to call it for_user), which filters your objects for you:

class Foo(models.Model):
    ts = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User, blank=True, null=True)
    due_date = models.DateField(auto_now=False)
    objects = CustomQuerySetManager()
    class QuerySet(QuerySet):
        def for_user(self, user):
            return self.filter(user=user)

From there, your view is fairly simple:

def view(request):
    user = request.user
    mylist = Foo.objects.for_user(user).filter(due_date__lte=datetime.date.today())
Jack M.
In this case I think it would make a lot more sense to use a method on the manager, instead of creating a custom QuerySet.
knutin
Actually, that's where the `CustomQuerySetManager` comes in handy from the other question. The code from the `QuerySet` works in the Manager as well. No breaking DRY.
Jack M.
A: 

To add to Jack's answer, your CustomQuerySetManager would be something like:

class CustomQuerySetManager(models.Manager):
    def get_query_set(self):
        return self.model.QuerySet(self.model)
    def __getattr__(self, attr, *args):
        return getattr(self.get_query_set(), attr, *args)

I prefer this method over writing manager methods because it allows you to have chainable functions, therefore you could do:

Foo.objects.for_user(user).filter(...)
zsquare