Проблема с изменяемой областью видимости в Python - PullRequest
0 голосов
/ 03 декабря 2009

Эта проблема частично объясняется отсутствием у меня полного понимания области видимости в python, поэтому мне нужно будет это рассмотреть. В любом случае, это серьезный тривиальный фрагмент кода, который постоянно падает в моем тестовом приложении Django.

Вот фрагмент:

@login_required
def someview(request):
 try:
  usergroup = request.user.groups.all()[0].name
 except:
  HttpResponseRedirect('/accounts/login')

 if 'client' in usergroup:
  stafflist = ProxyUserModel.objects.filter(groups__name='staff')

Здесь нет операции на головном мозге, проблема в том, что я получаю ошибку, такую ​​как:

 File "/usr/local/django/myapp/views.py", line 18, in someview
   if 'client' in usergroup:

UnboundLocalError: local variable 'usergroup' referenced before assignment

Мой вопрос здесь, почему группа пользователей не связана? Если он не связан, это означает, что в операторе try было сгенерировано исключение, и в этот момент должно произойти HttpResponseRedirect, но этого не произойдет. Вместо этого я получаю ошибку HTTP 500, что немного сбивает с толку.

Да, я могу написать более разумный код и убедиться, что входящий пользователь определенно имеет группу, связанную с ним. Но это не производственное приложение, я просто пытаюсь понять / изучить Python / Django. Почему именно это происходит, когда пользователь, не связанный с группой, входит в систему, а не перенаправляет на страницу входа?

В этом случае я намеренно захожу в систему как пользователь, который не является частью группы. Это означает, что приведенный выше код должен вызвать исключение IndexError, как показано ниже:

>>> somelist = []
>>> print somelist[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

Ответы [ 3 ]

10 голосов
/ 03 декабря 2009
HttpResponseRedirect('/accounts/login')

Вы создаете это, но не возвращаете это. Поток продолжается до следующей строки, которая ссылается на usergroup, несмотря на то, что она никогда не назначалась из-за исключения.

except тоже хлопотно. В общем, вы никогда не должны ловить «все» (except: или except Exception:), так как существует множество странных условий, которые вы можете выбросить, что делает отладку очень сложной. Либо перехватите определенный подкласс исключений, который, по вашему мнению, произойдет, когда пользователь не вошел в систему, либо, лучше, используйте тест if, чтобы проверить, не вошли ли они в систему. (Это не совсем исключительное условие.)

например. в Джанго обычно:

if not request.user.is_authenticated():
    return HttpResponseRedirect('/accounts/login')

или если вас беспокоит то, что пользователь не входит ни в одну группу (из-за сбоя [0]):

groups= request.user.groups.all()
if len(groups)==0:
    return HttpResponseRedirect('/accounts/login')
usergroup= groups[0].name
0 голосов
/ 03 декабря 2009

В тех случаях, когда у вас есть набор try…except, и вы хотите, чтобы код выполнялся, если * исключений не произошло, рекомендуется написать код следующим образом:

try:
    # code that could fail
except Exception1:
    # handle exception1
except Exception2:
    # handle exception2
else: # the code-that-could-fail didn't
    # here runs the code that depends
    # on the success of the try clause
0 голосов
/ 03 декабря 2009

Попробуйте переместить вас, если часть «клиент» внутри вас попытается заблокировать. Либо так, либо определите usergroup = None прямо над попыткой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...