Search code examples
pythondjangourlconf

Python Django UnboundLocalError while calling a different function


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


Solution

  • 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>[^\.]+)'