我正在使用中间件来获取我的视图和模型中当前登录的用户.这有助于我例如仅返回创建或分配给登录用户的对象.请点击此链接查看我使用的中间件.
我将此中间件称为:
get_current_user()
Run Code Online (Sandbox Code Playgroud)
到目前为止这个工作正常.但现在我经历了一些奇怪的行为,只针对一个特殊的用例.
我在自定义管理器中使用此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)
Run Code Online (Sandbox Code Playgroud)
在项目模型中,我设置了一个名为user_objects的自定义管理器.项目模型看起来像这样(简化):
class Project(models.Model):
name = models.CharField(max_length=100)
#Managers
objects = models.Manager()
user_objects=UserProjectManager()
Run Code Online (Sandbox Code Playgroud)
UserProjectManager()现在是我的关注点.经理看起来像这样:
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())
Run Code Online (Sandbox Code Playgroud)
我添加print "current user is" + str(get_current_user())了以便调试它.这个打印声明总是!打印出当前登录的用户.当我创建此函数时,服务器(manage.py runserver)正在运行,我没有重新启动服务器,并且该方法按照我的预期运行.
但是,如果我使用manage.py runserver重新启动服务器,则UserProjectManager()会因此错误而崩溃:
caught an exception while rendering: Incorrect integer value: 'AnonymousUser' for column 'member_id' at row 1
Run Code Online (Sandbox Code Playgroud)
我上传了错误页面:链接
有趣的是,当我让服务器运行时(在抛出错误之后)然后在我的源代码中更改某些内容(添加一个符号并删除它)并保存它(在我的项目中的某个地方,无所谓! ),再次点击抛出错误的链接,它的工作原理!更有趣的是
print "current user is" + str(get_current_user())
Run Code Online (Sandbox Code Playgroud)
在抛出错误的行前面,始终正确返回登录用户!
这对我来说没有多大意义.特别是因为它可以工作,如果我只是重新保存(这导致自动重启服务器!)我的来源.
我100%确定在上面列出的源代码行中创建了错误,因为我改变了这个:
return super(UserProjectManager, self).get_query_set().filter(projectmembership__member=get_current_user())
Run Code Online (Sandbox Code Playgroud)
对此:
return super(UserProjectManager, self).get_query_set())
Run Code Online (Sandbox Code Playgroud)
然后它工作得很好.我只是这样说,因为上面发布的错误可能是一个误导性的出价.
可能很难帮我在这里.非常感谢任何帮助!
编辑:
下面第一个回答"whrde"表示中间件方法可能是一个坏主意,而另一个线程链接的人说这种方法很好.
因此,我想说明这样一个中间件非常方便使用的另一个例子.我在我的应用程序中使用它.如果我真的应该从我的应用程序中删除此中间件,我会感兴趣.因为我可能会得到比我发布的错误更多的错误或者方法很好.例如,覆盖模型的save方法并设置current_user在使用此中间件时非常容易.它节省了我在save()的每个视图中写相同的三行.
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)
created_by = models.ForeignKey(User, editable=False, related_name='project_membership_creator')
created = models.DateTimeField(auto_now_add=True, editable=False, verbose_name='creation date')
modified_by = models.ForeignKey(User, editable=False, related_name='project_membership_modifier')
modified = models.DateTimeField(auto_now=True, editable=False)
#Managers
objects = models.Manager()
user_objects=UserProjectMembershipManager()
class Meta:
unique_together = (("project", "member"),)
def __unicode__(self):
return u'%s in project: %s' % (self.member, self.project)
def save(self):
if not self.id:
self.created_by = get_current_user()
self.modified_by = get_current_user()
super(ProjectMembership, self).save()
Run Code Online (Sandbox Code Playgroud)
编辑:Conclusio:不要使用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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3097 次 |
| 最近记录: |