Django custom managers - how do I return only objects created by the logged-in user?

django, django-custom-manager, django-managers, django-models

Solution

One way to handle this would be to create a new method instead of redefining `get_query_set`. Something along the lines of:

class UserContactManager(models.Manager):
    def for_user(self, user):
        return super(UserContactManager, self).get_query_set().filter(creator=user)

class UserContact(models.Model):
    [...]
    objects = UserContactManager()

This allows your view to look like this:

contacts = Contact.objects.for_user(request.user)

This should help keep your view simple, and because you would be using Django's built in features, it isn't likely to break in the future.

Problem

I want to overwrite the custom objects model manager to only return objects a specific user created. Admin users should still return all objects using the objects model manager. Now I have found an approach that could work. They propose to create your own middleware looking like this: ``` #### myproject/middleware/threadlocals.py try: from threading import local except ImportError: # Python 2.3 compatibility from django.utils._threading_local import local _thread_locals = local() def get_current_user(): return getattr(_thread_locals, 'user', None) class ThreadLocals(object): """Middleware that gets various objects from the request object and saves them in thread local storage.""" def process_request(self, request): _thread_locals.user = getattr(request, 'user', None) #### end ``` And in the Custom manager you could call the `get_current_user()` method to return only objects a specific user created. ``` class UserContactManager(models.Manager): def get_query_set(self): return super(UserContactManager, self).get_query_set().filter(creator=get_current_user()) ``` Is this a good approach to this use-case? Will this work? Or is this like "using a sledgehammer to crack a nut" ? ;-) Just using: ``` Contact.objects.filter(created_by= user) ``` in each view doesn`t look very neat to me. EDIT Do not use this middleware approach !!! use the approach stated by Jack M. below After a while of testing this approach behaved pretty strange and with this approach you mix up a global-state with a current request. Use the approach presented below. It is really easy and no need to hack around with the middleware. create a custom manager in your model with a function that expects the current user or any other user as an input. ``` #in your models.py class HourRecordManager(models.Manager): def for_user(self, user): return self.get_query_set().filter(created_by=user) class HourRecord(models.Model): #Managers objects = HourRecordManager() #in vour view you can call the manager like this and get returned only the objects from the currently logged-in user. hr_set = HourRecord.objects.for_user(request.user) ``` See also this discussion about the middelware approach.

Original source

Related problems