django get“u current”u user()中间件-奇怪的错误消息,如果源代码是;更改为“,这将导致服务器自动重启

django get“u current”u user()中间件-奇怪的错误消息,如果源代码是;更改为“,这将导致服务器自动重启,django,Django,我正在使用中间件在视图和模型中获取当前登录的用户。例如,这有助于我仅返回创建或分配给登录用户的对象。请按照下面的说明查看我使用的中间件 我将此中间件称为: get_current_user() 到目前为止,这一切都很顺利。但是现在我经历了一些奇怪的行为,并且只针对一个特殊的用例 我在自定义管理器中使用此get_current_user()仅返回当前登录用户是其成员的项目。成员资格是通过模型“ProjectMembership”定义的。此模型如下所示: class ProjectMembersh

我正在使用中间件在视图和模型中获取当前登录的用户。例如,这有助于我仅返回创建或分配给登录用户的对象。请按照下面的说明查看我使用的中间件

我将此中间件称为:

get_current_user()
到目前为止,这一切都很顺利。但是现在我经历了一些奇怪的行为,并且只针对一个特殊的用例

我在自定义管理器中使用此get_current_user()仅返回当前登录用户是其成员的项目。成员资格是通过模型“ProjectMembership”定义的。此模型如下所示:

class ProjectMembership(models.Model):
    project = models.ForeignKey(Project)
    member = models.ForeignKey(User, related_name='project_membership_member_set')
    day_rate = models.PositiveIntegerField(max_length=11)
class UserProjectManager(models.Manager):
    def get_query_set(self):
        print "current user is" + str(get_current_user())
        return super(UserProjectManager, self).get_query_set().filter(projectmembership__member=get_current_user())
在项目模型中,我设置了一个名为user\u objects的自定义管理器。项目模型如下所示(简化):

UserProjectManager()现在是我关心的问题。经理看起来像这样:

class ProjectMembership(models.Model):
    project = models.ForeignKey(Project)
    member = models.ForeignKey(User, related_name='project_membership_member_set')
    day_rate = models.PositiveIntegerField(max_length=11)
class UserProjectManager(models.Manager):
    def get_query_set(self):
        print "current user is" + str(get_current_user())
        return super(UserProjectManager, self).get_query_set().filter(projectmembership__member=get_current_user())
为了调试它,我添加了
print“current user is”+str(get\u current\u user())
。 这张打印的声明永远!打印出当前登录的用户。当我创建这个函数时,服务器(manage.py runserver)正在运行,我没有重新启动服务器,方法也没有像我预期的那样运行

但是,如果使用manage.py runserver重新启动服务器,UserProjectManager()将崩溃,并出现以下错误:

caught an exception while rendering: Incorrect integer value: 'AnonymousUser' for column 'member_id' at row 1
我上传了错误页面:

有趣的是,当我让服务器运行(在抛出错误后),然后在源代码中更改某些内容(添加一个符号并删除它)并保存它(在我的项目中的某个地方,无论在哪里!!),再次单击抛出错误的链接,它就工作了!更有趣的是

print "current user is" + str(get_current_user())
在抛出错误的行前面,始终正确返回已登录的用户

这对我来说没有多大意义。特别是如果我只是重新保存(这会导致服务器自动重新启动!)我的源代码,它就可以工作了

我100%确定错误是在上面概述的源代码行中创建的,因为我更改了以下内容:

return super(UserProjectManager, self).get_query_set().filter(projectmembership__member=get_current_user())
为此:

return super(UserProjectManager, self).get_query_set())
然后它工作得非常好。我只是这么说,因为上面张贴的错误可能是一个出价误导

在这里帮我可能很难。非常感谢您的帮助

编辑:

下面来自“whrde”的第一个答案指出,中间件方法可能是一个坏主意,而另一个线程中的人则表示该方法很好

因此,我想说明另一个这样的中间件使用起来非常方便的例子。我在我的应用程序中都使用它。如果我真的要从我的应用程序中删除这个中间件,我会很感兴趣。因为我可能会得到比我发布的错误更多的错误,或者这种方法很好。例如,在使用该中间件时,覆盖模型的save方法并设置当前用户非常容易。在save()之后,在每个视图中写入相同的三行代码可以节省我的时间


编辑:结论:不要使用get_current_user()中间件,因为绝对不需要使用它。将请求对象传递给窗体、对象管理器、覆盖对象保存方法等。。一切都会好起来的;-)

这看起来是一种糟糕的方法:您需要传递请求对象,以提供对当前用户具有访问权限的函数/类/方法。不要与一个全球国家为伍

在管理器上创建一个将用户作为参数的方法,并从视图中调用该方法:

# models.py
class ProjectMembership(models.Model):
    project = models.ForeignKey(Project)
    member = models.ForeignKey(User, related_name='project_membership_member_set')
    day_rate = models.PositiveIntegerField(max_length=11)

class ProjectManager(models.Manager):
    def for_user(self, user):
        return self.get_query_set().filter(projectmembership__member=user)

class Project(models.Model):
    name    = models.CharField(max_length=100)
    objects = ProjectManager()

# somewhere deep in views.py
if request.user.is_authenticated():
    Project.objects.for_user(request.user)

忽略线程本地sideshow,您的问题可能与以下事实有关:
AnonymousUser
对象实际上不是
User
模型实例。使用此对象查询数据库可能不会有太大帮助。您将希望在某个点检查已验证的用户,或者在视图中:

if request.user.is_authenticated():
    Project.objects.for_user(request.user)
或者在您的经理方法中:

def for_user(self, user):
    if user.is_authenticated():
        return self.get_query_set().filter(projectmembership__member=user)
    else:
        return self.get_query_set().none()

我似乎不清楚为什么需要求助于中间件。您可以简单地将request.user传递给某个查询以获得所需的查询集。为了在模型管理器中获得当前用户,您必须使用某种中间件,因为您无法将请求对象传递给您的models.py。MyModel.objects.some_自定义方法(request.user)有什么问题?我一直都在做类似的事情。这是一种比使用中间件和线程本地存储更简单、更明确的方法。非常感谢。我会这样做。如果几周前有人告诉我这件事,那就太好了;-)我会把这个问题留几天不回答,因为我真的想知道为什么会发生这种行为。实际上,请看我问题的编辑。你认为在覆盖模型save()方法中使用这种中间件也不是一个好主意吗?如果你只使用django的admin,你可以重载
ModelAdmin.save\u model(self,request,obj,form,change)
方法,在保存之前设置
obj.user=request.user
。请注意,Django的方法不是使用thread local(参见示例)。如果您愿意,您可以自由使用threadlocal hack,但有一个强烈的反对理由。没必要。传递用户对象比threadlocal hack更灵活、更明确、更易读、更简单,而且您可以自由编写方法和函数,使其更容易/更方便。@Tom它确实有效。您需要发布代码或询问其他问题以获得更多帮助。这不是问题所在,因为我使用@login\u required decorator,并且只有在用户登录时才能调用出现问题的视图。正如我所说,打印“current user is”+str(get_current_user())确实返回登录用户,这真的很奇怪。