[英]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. 在每个视图中看起来都不是很整洁。
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.