35

我想覆盖自定义对象模型管理器以仅返回特定用户创建的对象。管理员用户仍应使用对象模型管理器返回所有对象。

现在我找到了一种可行的方法。他们建议创建您自己的中间件,如下所示:

#### 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

在自定义管理器中,您可以调用该get_current_user()方法以仅返回特定用户创建的对象。

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

这是解决这个用例的好方法吗?这行得通吗?或者这就像“用大锤敲碎坚果”?;-)

只需使用:

Contact.objects.filter(created_by= user)

在每个视图中对我来说都不是很整洁。

编辑不要使用这种中间件方法!!!

使用下面 Jack M. 所述的方法

经过一段时间的测试后,这种方法的表现非常奇怪,并且通过这种方法,您将全局状态与当前请求混合在一起。

使用下面介绍的方法。这真的很容易,无需使用中间件。

在您的模型中创建一个自定义管理器,其函数期望当前用户或任何其他用户作为输入。

#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)

另请参阅有关 middelware 方法的讨论。

4

3 回答 3

57

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.

于 2010-01-29T16:15:56.117 回答
6

似乎有必要使用中间件来存储用户信息。

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

由于您将仅在@login_required不需要中间件中所有复杂错误处理的视图中使用它。

Just my 2¢.

于 2010-01-05T13:55:19.577 回答
-1

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()
于 2017-08-22T10:50:00.343 回答