简体   繁体   English

Django自定义管理器 - 如何仅返回登录用户创建的对象?

[英]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. 在自定义管理器中,您可以调用get_current_user()方法仅返回特定用户创建的对象。

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 使用下面Jack M.所述的方法

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. 另请参阅有关middelware方法的讨论

One way to handle this would be to create a new method instead of redefining get_query_set . 处理此问题的一种方法是创建一个新方法,而不是重新定义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. 这应该有助于保持您的视图简单,并且因为您将使用Django的内置功能,所以它不太可能在将来中断。

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. 但是,我宁愿不修改默认的ModelManager objects ,而是将它连接到另一个管理器,我将在代码中使用,比如在你的情况下使用user_objects而不是对象。

Since you will use this only within views that are @login_required you dont need all the complex error handling in the Middleware. 由于您只在@login_required视图中使用它, @login_required您不需要中间件中的所有复杂错误处理。

Just my 2¢. 只是我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. 控制管理器创建会更好,但Django不允许这样做。

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: 您可以在用户的​​视图中查询HourRecords ,只需:

request.user.hour_records.all()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 Django 中,我如何知道当前登录的用户? - In Django, how do I know the currently logged-in user? 如何使用Django将一个页面显示给已登录的用户,将另一个页面显示给未登录的用户? - How do I show one page to logged-in user and another to a not-logged in user with Django? 如何在 Django 中获取登录用户的用户名? - How can I get the username of the logged-in user in Django? Django:如何在基于 class 的视图中获取登录用户的用户名? - Django: How do I get the username of the logged-in user in my class based view? 如何从数据库中为 Django Rest Framework 中的登录用户返回数据? - How to return data from a database for a logged-in user in Django Rest Framework? Django Admin:如何在自定义“ list_display”字段中访问登录用户以使用它? - Django Admin: How to Access to Logged-in User for Using It in Custom 'list_display' Field? 我如何查看Django中已登录用户以外的用户信息? - How can I see user information other than the logged-in user in Django? 如何在Django views.py中获取登录用户的用户名 - How can I get the username of the logged-in user in Django views.py 仅当登录用户是创建 object 的用户时,如何使编辑和取消链接出现? Django - How do I make the edit and cancel link appear only if its the logged in user is the one who created the object? Django django:如何显示每个模板中登录的用户? - django: how to display user logged-in in each template?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM