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

柔情痞子 提交于 2019-12-17 07:05:44

问题


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.


回答1:


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.




回答2:


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¢.




回答3:


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.




回答4:


Or even simpler and use foreign key to retrieve queryset.

If you have model like that

class HourRecord(models.Model):
    created_by = ForeignKey(get_user_model(), related_name='hour_records')

You can query HourRecords in a view by user with simply:

request.user.hour_records.all()


来源:https://stackoverflow.com/questions/2006295/django-custom-managers-how-do-i-return-only-objects-created-by-the-logged-in-u

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!