UnboundLocalError: local variable 'books' referenced before assignment

345 views
Skip to first unread message

Joe Dunst

unread,
Mar 20, 2017, 9:38:38 AM3/20/17
to web2py-users

I'm trying to make a "vote up" and "vote down" feature in my program, like the one in reddit.com. But I've been receiving tickets from 2 different errors. (I solved the first one but I want to 
First, I received a "UnboundLocalError: local variable 'books' referenced before assignment"
This was my code at the time when I had that error.
CONTROLLER
def vote_callback():
    vars = request.post_vars
    if vars and auth_user:
        id = vars.id
        direction = +1 if vars.direction == 'up' else -1
        books = db.books(id)
        if books:
            votes = db.votes(post=id, created_by=auth.user.id)
            if not votes:
                books.update_record(vote_book=books.book_vote+direction)
                db.votes.insert(post=id,score=direction)
            elif votes.score!=direction:
                books.update_record(vote_book=books.book_vote+direction)
                votes.update_record(score=direction)
            else:
                pass
        print books.book_vote
    return str(books.book_vote)


VIEW:
<head>
    <script type = "text/javascript" src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

</head>
<body>

<h1>This is the default/list_books_by_vote.html template</h1>

{{if request.function=='list_books_by_vote':}}
{{=A('sort by datetime', _class='btn', _href=URL('list_books_by_datetime'))}}

{{elif request.function=="list_books_by_datetime":}}
{{=A('sort by votes', _class='btn', _href=URL('list_books_by_vote'))}}

{{else:}}
<h1>
        {{=author(user_id)}}
</h1>
{{pass}}

{{for post in rows:}}
<div class="well">
    <table>
        <tr data-id="{{=post.id}}">
            <td>
                <button data-direction="down" class="btn btn-primary">
                    Remove vote
                </button>
             </td>
            <td>
                <span class="votes">
                    {{=post.book_vote}}
                </span>
             </td>
            <td>
                <button data-direction="up" class="btn btn-success" style="margin-left:5px;margin-right:5px;">
                    I referenced this!
                </button>
            </td>
            <td>
                <strong>{{=A(post.book_title, _href=URL('show_specific_user', args=post.id))}}</strong>
            </td>
            <td>
                <span>
                    {{=author(post.modified_by)}}
                </span>
            </td>
        </tr>
    </table>
</div>
{{pass}}

<script type = "text/javascript">
    function do_ajax_vote(t, direction) {
        var id = jQuery(t).closest('tr').attr('data-id');
        jQuery.ajax({method:'post',url:'{{=URL('vote_callback')}}',
                     data:{'id':id,'direction':direction},
                     success: function(data){
                         jQuery(t).closest('tr').find('.votes').html(data);
        } });
        }

    jQuery(function() {
        jQuery('[data-direction=up]').click(function(){do_ajax_vote(this, 'up');});
        jQuery('[data-direction=down]').click(function(){do_ajax_vote(this, 'down');});
    });
</script>
</body>

Model:
db.define_table('books',
                Field('book_title', 'string', requires=(IS_NOT_IN_DB(db,'books.book_title'), IS_NOT_EMPTY()), label='Thesis Title'),
                Field('book_subtitle', 'string', label='Thesis Subtitle (Optional)'),
                Field('book_date', type='date', requires=IS_DATE(), label='Publish Date' ),
                Field('book_abstract', type='text', requires=IS_NOT_EMPTY() , label='Thesis Abstract' ),
                Field('book_school', requires=IS_IN_SET(['AMA Computer College - Naga Campus', 'Ateneo de Naga University', 'Naga College Foundation', 'Computer Communication Development Institute', 'University of Nueva Caceres']), label='Orginating School' ),
                Field('book_location', requires=IS_IN_SET(['AMA Computer College - Naga Campus', 'Ateneo de Naga University', 'Naga College Foundation', 'Computer Communication Development Institute', 'University of Nueva Caceres']), label='Location' ),
                Field('book_proponents', requires=IS_NOT_EMPTY(), label='Thesis Proponents' ),
                Field('book_category', requires=IS_IN_SET(['Education, Science and Teacher Training', 'Fine and Applied Arts', 'Humanities', 'Religion and Theology', 'Social Behavioral Sciences', 'Business Administration and Related', 'Law and Jurispusence', 'Natural Science', 'Mathematics', 'IT-Related Disciplines', 'Engineering and Tech', 'Medical and Allied', 'Trade, Craft and Industrial', 'Architecture and Town Planning', 'Agriculture, Forestry, Fisheries', 'Home Economics', 'Service Trades', 'Mass Communication and Documentation', 'Maritime', 'General', 'Other Disciplines']), label='Thesis Category' ),
                Field('book_level', requires=IS_IN_SET(['Undergraduate', 'Masteral']), label='Thesis Level' ),
                Field('book_course', requires=IS_IN_SET(['Bachelor of Science in Information Technology', 'Bachelor of Science in Computer Science']), label='Proponent\'s Course' ),
                Field('book_vote', 'integer', default=0, readable=True, writable=True),
                auth.signature
                )

db.define_table('votes',
                Field('books', 'reference books'),
                Field('score', 'integer', default=+1),
                auth.signature
               )

I "solved" the problem when I searched the internet and saw this "http://stackoverflow.com/questions/15217145/local-variable-author-referenced-before-assignment". I learned that I should transfer these lines: 
id = vars.id
books = db.books(id)
outside of the loop. I did that so I'm not getting that error anymore.



Now, I'm getting another error when I transfered the two varianles outside the loop. I tried looking for answers in the internet to no avail.
The error is: 
UnboundLocalError: local variable 'books' referenced before assignment

CONTROLLER
def vote_callback():
    vars = request.post_vars
    id = vars.id
    books = db.books(id)
    if vars and auth_user:
        direction = +1 if vars.direction == 'up' else -1
        if books:
            votes = db.votes(post=id, created_by=auth.user.id)
            if not votes:
                books.update_record(vote_book=books.book_vote+direction)
                db.votes.insert(post=id,score=direction)
            elif votes.score!=direction:
                books.update_record(vote_book=books.book_vote+direction)
                votes.update_record(score=direction)
            else:
                pass
        print books.book_vote
    return str(books.book_vote)

VIEW:
The same

Model:
The same

P.S.
-I highlighted the relevant parts of the code.
-The View and the Model is working. I think the problem with the code is in the controller.
-I'm trying to do this at 27:58 
https://www.youtube.com/watch?v=DIOFcDIlHWI&index=3&list=PLG0pjuN991OmU891IjbxOss3kYEz_JMR7


Thanks in advance.

Anthony

unread,
Mar 20, 2017, 12:32:02 PM3/20/17
to web2py-users
Show the full traceback and indicate the line of code actually throwing the error.

Mirek Zvolský

unread,
Mar 20, 2017, 1:45:27 PM3/20/17
to web...@googlegroups.com
This has nothing with Web2py but with Python.

Try this:
>>> a = 5
>>> def f():
if False:
a = 3
return a
>>> f()
UnboundLocalError: local variable 'a' referenced before assignment

And this is exactly what you have in vote_callback() with variable books.
Python can work with variables from outer scope and use them readonly.
However here Python will determine that 'books' (or 'a') is readwrite - and you haven't set it yet (if condition 'vars and auth_user' is False) and you want get its value (in 'return' command).
Reply all
Reply to author
Forward
0 new messages