当前位置: 动力学知识库 > 问答 > 编程问答 >

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

问题描述:

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.

网友答案:

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.

网友答案:

It seems necessary to use the middleware to store the user information.

However, I'd rather not modify the default ModelManager objects, but hook it upto a different manager, that I will use in the code, say in your case user_objects instead of objects.

Since you will use this only within views that are @login_required you dont need all the complex error handling in the Middleware.

Just my 2¢.

网友答案:

Thank you for sharing the code. Not so good solution in terms of testability but I did not find another way to customize model managers by request object data. It would be better to have control over manager creation but Django does not allow this.

分享给朋友:
您可能感兴趣的文章:
随机阅读: