Промежуточное ПО django get_current_user() - странное сообщение об ошибке, которое исчезает, если исходный код "изменен", что приводит к автоматическому перезапуску сервера
Я использую промежуточное программное обеспечение, чтобы получить вошедшего в систему пользователя в моих представлениях и моделях. Это помогает мне, например, возвращать только объекты, созданные или назначенные вошедшему в систему пользователю. Пожалуйста, перейдите по этой ссылке, чтобы увидеть, какое промежуточное программное обеспечение я использую.
Я называю это промежуточное программное обеспечение с:
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)
В модели проекта я установил собственный менеджер с именем user_objects. Модель проекта выглядит так (упрощенно):
class Project(models.Model):
name = models.CharField(max_length=100)
#Managers
objects = models.Manager()
user_objects=UserProjectManager()
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())
я добавил 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
Я загрузил страницу с ошибкой: ссылка
Интересно, что когда я позволяю серверу работать (после того, как ошибка была выдана), а затем что-то изменить в моем исходном коде (добавить знак и удалить его) и сохранить его (где-то в моем проекте, не имеет значения, где!!), нажмите еще раз на ссылку, которая выкинула ошибку, все работает! Более интересным является то, что
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" говорится, что подход промежуточного программного обеспечения, вероятно, является плохой идеей, в то время как люди из другой ветки ссылок сказали, что подход хорош.
Поэтому я хотел привести другой пример, где такое промежуточное ПО действительно удобно использовать. Я использую все это в моем приложении. Мне было бы интересно, если бы мне действительно пришлось удалить это промежуточное ПО из моего приложения. так как, вероятно, я получу больше ошибок, чем тот, который я опубликовал или что подход в порядке. Например, переписать метод сохранения для модели и установить 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()
Редактирование: Заключение: не используйте промежуточное программное обеспечение get_current_user(), так как его абсолютно не нужно использовать. Передайте объект запроса вашим формам, менеджерам объектов, перезаписанным методам сохранения объектов и т. Д., И все будет хорошо;-)
2 ответа
Это выглядит как плохой подход: вам нужно передать объект запроса, чтобы предоставить функции / классу / методу доступ к текущему пользователю. Не связывайтесь с глобальным состоянием.
Создайте метод в вашем менеджере, который принимает пользователя в качестве аргумента, и вызывайте его из ваших представлений:
# 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)
Не обращая внимания на локальное обсуждение потока, ваша проблема, вероятно, связана с тем, что 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()