Search code examples
python-2.7sqlalchemybooleancrudtraceback

Update boolean in SQL Alchemy (using CRUD)


I am trying to update the boolean statement from the default False to True. The idea here is that a user watches some video and the update method changes from False to True.

I am struggling with writing the update_view_state method. I have tried dot notation (I am admittedly new to this) and have been unsuccessful.

Using Python 2.7 SQLALCHEMY and CRUD method

class View_State(Base):
    __tablename__ = 'view_states'
    #more code
    completed = Column(Boolean, default=False) #have to set default

    def __init__(self, user, video):
        self.completed = False

Update code:

def update_view_state(self, username, videoname, completed):
    #update Boolean completed status to 'complete = True'
    update_view = self.session.query(View_State).\
    filter(View_State.user.has(username == username)).\
    filter(View_State.video.has(videoname == videoname)).one()
    if update_view:
        print 'update view found: ', update_view.completed
        update_view.completed.append(completed)
        self.session.commit()
        return update_view

Test.py

api.update_view_state('ack', 'module1', True)

Traceback:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/Users/ack/code/enotss_copy/NotssDB/notssdb/test/test.py", line 296, in test_crud_operations
    api.update_view_state('ack', 'module1', True)
  File "/Users/ack/code/enotss_copy/NotssDB/notssdb/api/convenience.py", line 35, in update_view_state
    return super(ConvenienceAPI, self).update_view_state(user, video, completed)
  File "/Users/ack/code/enotss_copy/NotssDB/notssdb/api/object.py", line 634, in update_view_state
    filter(View_State.user.has(username == username)).\
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 442, in has
    return self.operate(PropComparator.has_op, criterion, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 175, in operate
    return op(self.comparator, *other, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 383, in has_op
    return a.has(b, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1172, in has
    return self._criterion_exists(criterion, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1081, in _criterion_exists
    criterion = criterion._annotate(
AttributeError: 'bool' object has no attribute '_annotate'

with ANSWER from below:

traceback:

ERROR: notssdb.test.test.test_crud_operations
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/Users/ack/code/enotss_copy/NotssDB/notssdb/test/test.py", line 295, in test_crud_operations
    api.update_view_state('ack', 'module1', True)
  File "/Users/ack/code/enotss_copy/NotssDB/notssdb/api/object.py", line 628, in update_view_state
    filter(View_State.user.has(username == username)).\
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 442, in has
    return self.operate(PropComparator.has_op, criterion, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 175, in operate
    return op(self.comparator, *other, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 383, in has_op
    return a.has(b, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1172, in has
    return self._criterion_exists(criterion, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1081, in _criterion_exists
    criterion = criterion._annotate(
AttributeError: 'bool' object has no attribute '_annotate'

Solution

  • In response to your comment, I think it's better I just post an answer to provide the detail. Hopefully this helps you get it cleared up and running properly.

    def update_view_state(self, username, videoname, completed):
        #update Boolean completed status to 'complete = True'
        update_view = self.session.query(View_State).\
        filter(View_State.user.has(username == username)).\
        filter(View_State.video.has(videoname == videoname)).one()
        if update_view:
            print 'update view found: ', update_view.completed
            update_view.completed = True # Simply reassign it like a variable
            self.session.add(update_view) # Add it to the session
            self.session.commit() # And commit
            return update_view
    

    I've used self.session in the code, because that's what you're using. I've never set up my sessions that way, so I've only ever used session.commit() or session.add(), but I'm trying to stay consistent with what you've got posted, as that may be required by some other, unposted, part of your code.

    I've directly updated to the boolean True here, but I see that you've taken in a function paremeter completed that you may prefer to use. In that case, simply use update_view.completed = completed. Perhaps consider renaming that parameter to avoid confusion with the column in your database bearing the same name.

    As you asked, if we rename the parameter completed to status_change it would look like this:

    def update_view_state(self, username, videoname, status_change):
        #update Boolean completed status to 'complete = True'
        update_view = self.session.query(View_State).\
        filter(View_State.user.has(username == username)).\
        filter(View_State.video.has(videoname == videoname)).one()
        if update_view:
            print 'update view found: ', update_view.completed
            update_view.completed = status_change # Simply reassign it like a variable
            self.session.add(update_view) # Add it to the session
            self.session.commit() # And commit
            return update_view
    

    In this case, you would be able to use the function to set update_view.completed to either True or False if you wanted to switch back and forth. Doing so would just be a matter of passing the Boolean of your choice in as an argument to the function. If you only ever want to set it to True using this function, then you could remove the status_change parameter entirely, and use the raw Boolean value as in the first example.