سؤال

Not long ago I started programming Python with Django. Sometimes I get strange errors and have no clue, why. So, let's beginn with one of these errors.

I have a View with two functions. Example:

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)

Then calling them with my URLconf. Calling view_post function works as It should, without errors.

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'),

...

But calling the new_post function runs in a UnboundLocalError Exception on line 39 "local variable 'post' referenced before assignment". Line 39 is render_to_response of the view function, not the new function.

So, why the heck is my call of the new function throwing an error in my view function? Really, I have no clue. I came over from C# so I'm sure I didn't get some special Python rule which makes me coding things wrong.

Update: The indentation of the two functions isn't correct because of stackoverflow.com code panel. Don't care about it.

enter image description here

هل كانت مفيدة؟

المحلول

The problem is the indentation

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

Is different for python of:

def view(request):
    ...

def new(request):
    ...

You should be sure use spaces for indentation and python recommends 4 spaces instead of tab

Update:

The problem is in urls:

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

Change it to:

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

That is because the url /new/ match the regexp

r'^(?P<slug>[^\.]+)'

نصائح أخرى

The error definitely sounds like the view_post view function is being called. Are you sure that your urlpatterns are the right way around? Or both URL regexes could be pointed at view_post.

In view_post if the query finds no items, then the variable post that is only set in the for loop will not have been set, and the reference to it in render_to_response will raise the UnboundLocalError.

You can avoid that by setting post to None before the loop.

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)

You can see why the UnboundLocalError is happening using this simpler function:

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

(Obviously, you wouldn't really implement first_element like this, but this illustrates what's happening.) If you call first_element with a non-empty list, it'll work as expected:

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

But if you call it with an empty list, result has never been bound, so you'll get the error:

>>> 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top