Python Django UnboundLocalError при вызове другой функции - PullRequest
0 голосов
/ 17 ноября 2011

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

У меня есть вид с двумя функциями. Пример:

def view_post(request, slug):
    """
    Shows a single post
    """
    posts = Post.objects(slug = slug).limit(1)
    for items in posts:
        post = items

    cssClasses = css_class_converter({ _css_class_editable })

    context = RequestContext(request)
    return render_to_response("single.html", { 'post': post, 'class': cssClasses }, context)

def new_post(request):
    '''
    Opens a blank page for creating a new post
    '''

    post = Post()
    cssClasses = css_class_converter({ _css_class_editable, _css_class_new })
    context = RequestContext(request)
    return render_to_response("single.html", {'post': post, 'new': True }, context)

Затем вызываю их с помощью моего URLconf. Вызов функции view_post работает как надо, без ошибок.

urlpatterns = patterns('blog.views',
    # Examples:
    url(r'^$', views.index),
    url(r'^(?P<slug>[^\.]+)', 'view_post', name='view_blog_post'),
    url(r'^new/$', 'new_post', name='new_blog_post'),

...

Но вызов функции new_post выполняется в исключении UnboundLocalError в строке 39 «локальная переменная« post », на которую ссылается до присвоения» . Строка 39 - это render_to_response функции view, а не новой функции.

Итак, почему, черт возьми, мой вызов функции new выдает ошибку в моей функции view ? Действительно, я понятия не имею. Я пришел из C #, так что я уверен, что не получил какое-то специальное правило Python, которое заставляет меня неправильно кодировать вещи.

Обновление: отступ двух функций не корректен из-за панели кода stackoverflow.com. Не волнуйтесь об этом.

enter image description here

Ответы [ 2 ]

3 голосов
/ 17 ноября 2011

Проблема в отступе

def view(request):
    ...
    def new(request):
        ...

Отличается для питона:

def view(request):
    ...

def new(request):
    ...

Вы должны быть уверены, что для отступа используйте пробелы, а python рекомендует 4 пробела вместо табуляции

Обновление:

Проблема в URL:

url(r'^$', views.index),
url(r'^(?P<slug>[^\.]+)', 'view_post', name='view_blog_post'),
url(r'^new/$', 'new_post', name='new_blog_post'),

Измените его на:

url(r'^$', views.index),
url(r'^new/$', 'new_post', name='new_blog_post'),
url(r'^(?P<slug>[^\.]+)', 'view_post', name='view_blog_post'),

Это потому, что URL / новый / соответствует регулярному выражению

r'^(?P<slug>[^\.]+)'
1 голос
/ 17 ноября 2011

Ошибка определенно звучит так, как будто вызывается функция просмотра view_post.Вы уверены, что ваши urlpatterns правильные пути?Или оба регулярных выражения URL могут указывать на view_post.

В view_post, если запрос не находит элементов, тогда переменная post, заданная только в цикле for, не будет установлена, иссылка на него в render_to_response вызовет UnboundLocalError.

. Этого можно избежать, установив в столбце None перед циклом.

def view_post(request, slug):
        """
        Shows a single post
        """
        posts = Post.objects(slug = slug).limit(1)
        post = None   # Ensure post is bound even if there are no posts matching slug
        for items in posts:
            post = items

        cssClasses = css_class_converter({ _css_class_editable })

        context = RequestContext(request)
        return render_to_response("single.html", { 'post': post, 'class': cssClasses }, context)

Вы можете понять, почему UnboundLocalErrorпроисходит с использованием этой более простой функции:

def first_element(items):
    for item in items:
        result = item
        break
    return result

(Очевидно, что вы бы на самом деле не реализовали first_element, как это, но это иллюстрирует, что происходит.) Если вы вызываете first_element с непустым списком,он будет работать как положено:

>>> first_element([2, 3, 4])
2

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

>>> first_element([])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in first_element
UnboundLocalError: local variable 'result' referenced before assignment
...