Python class variable not updating - python

I have a class that is taking in an Id and trying to update the variable current_account but when I print out the details of the current_account it hasn't updated.
Anyone got any ideas for this? New to python so might be doing something stupid that I can't see.
class UserData:
def __init__(self, db_conn=None):
if None == db_conn:
raise Exception("DB Connection Required.")
self.db = db_conn
self.set_my_account()
self.set_accounts()
self.set_current_account()
def set_current_account(self, account_id=None):
print account_id
if None == account_id:
self.current_account = self.my_account
else:
if len(self.accounts) > 0:
for account in self.accounts:
if account['_id'] == account_id:
self.current_account = account
print self.current_account['_id']
else:
raise Exception("No accounts available.")
Assume that set_my_account() gets a dictionary of account data and that set_accounts() get a list of dictionaries of account data.
So when I do the following:
user_data = UserData(db_conn=db_conn)
user_data.set_current_account(account_id=account_id)
Where db_conn is a valid database connection and account_id is a valid account id.
I get the following out of the above two lines.
None
518a310356c02c0756764b4e
512754cfc1f3d16c25c350b7
So the None value is from the declaration of the class and then the next two are from the call to set_current_account(). The first id value is what I'm trying to set. The second id value is what was already set from the class __init__() method.

There were a lot of redundancies an un-Pythonic constructions. I cleaned up the code to help me understand what you trying to do.
class UserData(object):
def __init__(self, db_conn):
self.db = db_conn
self.set_my_account()
self.set_accounts()
self.set_current_account()
def set_current_account(self, account_id=None):
print account_id
if account_id is None:
self.current_account = self.my_account
else:
if not self.accounts:
raise Exception("No accounts available.")
for account in self.accounts:
if account['_id'] == account_id:
self.current_account = account
print self.current_account['_id']
user_data = UserData(db_conn)
user_data.set_current_account(account_id)
You used default arguments (db_conn=None) when a call without an explicit argument is invalid. Yes, you can now call __init__(None) but you could also call __init__('Nalum'); you can't protect against everything.
By moving the "No accounts" exception the block fast-fails and you save one level of indention.
The call UserData(db_conn=db_conn) is valid but unecessarily repetitive.
Unfortunately, I still can't figure out what you are trying to accomplish and this is perhaps the largest flaw. Variable names are terribly important for help the reader (which may be the future you) make sense of code. current_account, my_account, account_id and current_account['_id'] so obscure the intention that you should really consider more distinct, informative names.

Figured out what it was.
The data was being changed else where in the code base. It is now working as expected.
Thanks guys for pointing out the Python centric things that I was doing wrong, good to get it.

Related

sqlalchemy.exc.InterfaceError: <unprintable InterfaceError object> / Querying DB causes error with assigning seperate variable to list

For my web app I have some variables being injected into the base/all templates with the following code:
#app.context_processor
def inject_into_base():
# If user is not logged in
if not current_user.is_authenticated:
# Set count to none
count = None
role = None
# Else Count is set to the number of unread messages
else:
count = db.session.query(message).filter(message.user_id_to == current_user.user_id).filter(message.status == False).count()
role = db.session.query(user_society_role.role_id).filter_by(user_id=current_user.user_id).order_by(user_society_role.role_id.desc()).first().role_id
return dict(count=count, role=role)
All is well until I hit a certain route that contains the line:
Survey.q9 = Survey.q9.split(',')
Which just simply splits the string into a list. It results in
sqlalchemy.exc.InterfaceError: <unprintable InterfaceError object>
If I hard code the two db.session.query's found in inject_into_base it will run just fine, and if I comment out the .split(', ') in the route it also works fine.
I have also found assigning anything to Survey.q9 breaks my app, and ONLY on this one certain route.
Any help is much appreciated, this is my first time asking a question on here so please go easy on me :)
Fixed my issue, turns out sqlalchemy's autoflush feature was breaking my app, all I had to do to fix this was add db = SQLAlchemy(app, session_options={"autoflush": False}) to my __init__.py

Not receiving a return message in python 2 code

I'm pretty new to python and just learning to ropes. In the code bellow I have a function taking several inputs from a json string. I'm attempting to have a return output in the specified strings. Problem? when I run the file I get nothing... I'm sure I'm missing something incredibly simply, but for the life of me I can't figure out what. I've attempted to use return as well as print at the end of the function. No cheese.
Help?
Here's what I've got so far:
import datetime, json
def jeeves(request): #defines the function
message=''
if request['type']=='maintainance':
message='Thank you tenant at unit'+str(request['unit'])+', your request for maintenance to deal with '+'"'+str(request['issue'])+'"'+' has been received #2 input'
elif request['type']=='purchase':
message='Thank you tenant at unit'+str(request['unit'])+'your request to purchase a'+str(request['commodity'])+ ' has been received'
elif request['type']=='reservation':
startTime=request['date'].split(" ")[1]
startTime=startTime.split('')
time=0;
num=[]
for item in startTime:
if isdigit(item):
num.append(item)
for index in range(len(num)):
time+=num[index]*10**(len(num)-index)
endTime=0
daySplit=''.join(startTime[-2:])
if time+int(request['duration'].split(' ')[0])>12:
endTime=time+int(request['duration'].split(' ')[0])-12
if daySplit=='AM':
endTime=str(endTime)+'PM'
else:
endTime=str(endTime)+'AM'
else:
endTime=endTime+int(request['duration'].split(' ')[0])
endTime=str(endTime)+daySplit
message='Thank you tenant at unit'+str(request['unit'])+'your request to reserve our '+str(request['location'])+' on '+str(request['date'].split(' ')[0])+' from '+str(request['date'].split(' ')[1])+' to '+ endTime+' has been received'
elif request['type']=='complaint':
message='Thank you tenant at unit'+str(request['unit'])+' we will have someone follow up on '+'"'+request['issue']+'"'+' in regards to our '+request['location']
return message
print message
json.dumps(jeeves({"type":"maintenance", "unit":221, "issue":"Air filter needs replacing"}))
ps: I'm new to coding in general. If there is a better, more productive way for me to ask questions, I'm open to feedback. Thank you in advanced.
You have to put return before the print function because when you use return it ends a function. You might also want to check out what return actually does here

Web2Py using variables with db().count()

Ok this one should be an easy question id imagine, but cannot figure it out.
Im passing form data to the controller and attempting to do a data search there, which in turn, runs this..
def initLogin():
userName = request.vars.user_name;
counter = db(db.Users.UserName == userName).count()
if counter > 0:
return DIV("User exists")
return DIV("user does not exist")
I have checked the value is being passed correctly( which is is) by returning userName instead of the string, which shown me it was the correct value, and when i had a direct string of a correct username, it seemed to work. So my question is.. how do you run a count() function with web2py databases correctly using variables?
Your code is correct and shouldn't be giving you any problems, the only possible problem should be in your userName var not being what you expected or an incorrect sql query. I recommend that you try changing your controller to:
def initLogin():
userName = request.vars.user_name;
counter = db(db.Users.UserName == userName).count()
lastExecutedQuery = db._lastsql
return DIV( lastExecutedQuery )
And check if the query being performed is the one that you expected.

SQLAlchemy Session error

I have a problem with the session in SQLAlchemy, when i Add a row in the DB it's OK, but if i want to add another row without closing my app, It doesn't Add
This is the function in my Model:
def add(self,name):
self.slot_name = name
our_slot = self.session_.query(Slot).filter_by(slot_name = str(self.slot_name)).first()
if our_slot:
return 0
else:
self.session_.add(self)
self.session_.commit()
return 1
The problem is that you commit your session. After committing a session, it is closed. Either you commit after you are done adding, or you open a new session after each commit. Also take a look at Session.commit(). You should probably read something about sessions in SQLAlchemy's documentation.
Furthermore, suggest you do this:
def add(self,name):
self.slot_name = name
try:
our_slot = self.session_.query(Slot)\
.filter_by(slot_name = str(self.slot_name)).one()
self.session_.add(self)
return 1
except NoResultFound:
return 0
Of course, this only works if you expect exactly one result. It is considerd good practice to raise exceptions and catch them instead of making up conditions.

Mysterious behavior in try-except-finally

Excuse the vague title, I didn't know how else to state this.
I have a task worker request handler that fetches data from a URL and writes it to blobstore and saves the data's blob_key to a ListProperty in datastore. I've tried to simplifly the code for clarity here:
class Fetch(webapp2.RequestHandler):
def get(self):
url = self.request.get('url')
itemKey = self.request.get('itemKey')
item = MyModel.get(itemKey)
try:
result = urlfetch.fetch(url=url)
if result.status_code == 200:
saveDataResult = save_data(result.content, itemKey)
if saveDataResult is False:
raise Exception('error saving data')
else:
raise Exception('error fetching data: %s' % result.status_code)
item.status = 'success'
except Exception:
item.status = 'failed'
finally:
item.put()
def save_data(data, itemKey)
try:
#write data to blobstore and get its blob_key...
blob_key = files.blobstore.get_blob_key(file_name)
item = MyModel.get(itemKey)
item.blobKey.append(blob_key)
item.put()
return True
except:
return False
Now the problem I'm having is, when saveDataResult returns True, its status is set to 'success' but its blobKey property contains no value, even though a blob_key was generated and the data successfully written. I can't see what's causing this to save my life, please help.
Without much more information it is very difficult to determine what's happening. Here's my educated guess:
MyModel.get(itemKey) is called both in get() and save_data(). I surmise that it's returning two different objects representing the item. When the blobKey gets updated in save_data, the update is occurring only in the object fetched in save_data. When you later examine it outside that scope, you're looking at a different object.
Whether this is correct or not will depend on the implementation of MyModel.get().
Also, you do realize that you're calling item.put() twice, right?
The problem is here
finally:
item.put()
this single call overrides the data saved by save_data() because it references an older object of item.
My suggestion would be you do the status updates from save_data() i.e item.status = 'success'
or move item = MyModel.get(itemKey) to come after save_data() so you can fetch the updated object.
The problem is that when you call save_data() with item = MyModel.get(itemKey)
which is again called from the class Fetch you end up having two different objects and therefore overwriting the one in save_data() and hence when you go to your model datastore no data for blobkey is stored as its overwritten.
Try doing everything in the class or you do not use item = MyModel.get(itemKey) twice.

Categories

Resources