промежуточное ПО django get_current_user () - странное сообщение об ошибке, которое исчезает, если исходный код «изменен», что приводит к автоматическому перезапуску сервера - PullRequest
6 голосов
/ 18 января 2010

Я использую промежуточное программное обеспечение, чтобы получить зарегистрированного пользователя в моих представлениях и моделях. Это помогает мне, например, возвращать только объекты, созданные или назначенные вошедшему в систему пользователю. Перейдите по этой ссылке , чтобы узнать, какое промежуточное ПО я использую.

Я называю это промежуточное ПО с:

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) работал, и я не перезагружал сервер, и метод работает так, как я и ожидал.

Но если я перезапускаю сервер с помощью runserver manage.py, 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())

и тогда он отлично работает. Я просто говорю это, поскольку вышеприведенная ошибка, возможно, вводит в заблуждение ставку.

Вероятно, трудно помочь мне здесь. Буду признателен за любую помощь!

Edit:

В первом ответе ниже от "whrde" говорилось, что подход промежуточного программного обеспечения, вероятно, является плохой идеей, тогда как люди из другого потока link сказали, что подход хорош.

Поэтому я хотел бы привести еще один пример, когда такое промежуточное ПО действительно удобно использовать. Я использую все это в моем приложении. Мне было бы интересно, если бы мне действительно пришлось удалить это промежуточное ПО из моего приложения. так как, вероятно, я получу больше ошибок, чем тот, который я написал или что подход в порядке. Например, перезаписать метод сохранения для модели и установить 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()

Edit: Conclusio: не используйте промежуточное программное обеспечение get_current_user (), так как его совершенно не нужно использовать. Передайте объект запроса вашим формам, менеджерам объектов, перезаписанным методам сохранения объектов и т. Д., И все будет хорошо; -)

Ответы [ 2 ]

7 голосов
/ 18 января 2010

Это выглядит как плохой подход: вам нужно передать объект запроса, чтобы предоставить функции / классу / методу доступ к текущему пользователю. Не связывайтесь с глобальным состоянием.

Создайте метод в вашем менеджере, который будет принимать пользователя в качестве аргумента, и вызывайте его из ваших представлений:

# 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)
1 голос
/ 18 января 2010

Не обращая внимания на локальное представление потока, ваша проблема, вероятно, связана с тем, что объект 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...