I am stuck with a query in a function. here is my code:
def action(changePin, action):
pins = Pins.query.all()
changePin = int(changePin)
deviceName = Pins.query.filter_by(pin=changePin, name)
if action == "on":
GPIO.output(changePin, GPIO.HIGH)
print("turned ", deviceName , " on")
if action =="off":
GPIO.output(changePin, GPIO.LOW)
print("turned ", deviceName , " off")
for pin in pins:
db.session.commit()
The error for this is
File "<stdin>", line 4
SyntaxError: positional argument follows keyword argument
In line 4 I want to find the name of the pin relating to the pin "changePin", this is adapted code from a tutorial, here is the origional code where a dictionary holds the pin information not a database, code:
deviceName = pins[changePin]['name']
I have tried numerous different ways but none work, here is a list of the different versions of line 4:
deviceName = Pins.query.filter_by(changePin=pin).name
deviceName = Pins.query.filter_by(changePin, name=name)
deviceName = Pins.query.filter_by(Pins.pin=changePin, Pins.Name)
deviceName = Pins.query(Pins.pin=changePin, Pins.Name)
deviceName = Pins.query(**changePin, Pins.name)
deviceName = Pins.query(**changePin)
deviceName = db.session.filter_by(Pins.changePin)
deviceName = db.session(Pins).filter_by(pin=changePin)
and many other variations, I have read the sqlalchemy docs and the flask docs, but I have not seen any comparisons, I have looked at and tried this; flask sqlalchemy query with keyword as variable
but got this;
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in action
TypeError: BaseQuery object argument after ** must be a mapping, not int
this is my models.py code;
class Pins(db.Model):
id = db.Column(db.Integer, primary_key=True)
pin = db.Column(db.Integer, index=True, unique=True)
name = db.Column(db.String(64))
upDown = db.Column(db.String(4))
state = db.Column(db.String(9))
def __repr__(self):
return '<Valves {}>'.format(self.pin)
Querying with function on Flask-SQLAlchemy model gives BaseQuery object is not callable error
Dear Menno
Thank you for comming back to me I have followed your advice and it works!!!
rows = Pins.query.filter_by(pin=changePin).all()
deviceName = rows[0].name
I don't understand how the "rows[0].name" part works but it does,
thank you thank you
help
regards
Paul
A filter_by expression selects rows, not fields. From the documentation: "apply the given filtering criterion to a copy of this Query, using keyword expressions.". Name is not a keyword expression, just a name.
Also, after building the query, you have to run it. You do that by calling all() on it:
deviceName = Pins.query.filter_by(pin=changePin).all()
Letś also change the name of the outcome:
rows = Pins.query.filter_by(pin=changePin).all()
Calling that returns a list with zero or more rows, hence the name. rows[0] (the first row) is what you want. After you have a row, a field becomes an attribute of the row: rows[0].name. You can also use one() to get a unique row.
If you still need that: To limit the columns that are returned use load only cols
Related
I have the following api call to tda-api
orders = client.get_account(config.account_id,fields=['positions'])
Gives the Error:
File "/opt/anaconda3/lib/python3.7/site-packages/tda/client/base.py", line 361, in get_account
fields = self.convert_enum_iterable(fields, self.Account.Fields)
File "/opt/anaconda3/lib/python3.7/site-packages/tda/utils.py", line 66, in convert_enum_iterable
self.type_error(value, required_enum_type)
File "/opt/anaconda3/lib/python3.7/site-packages/tda/utils.py", line 41, in type_error
possible_members_message))
ValueError: expected type "Fields", got type "str". (initialize with enforce_enums=False to disable this checking)
the documentation follows:
Client.get_account(account_id, *, fields=None)
and if i replace with:
client.get_account(config.account_id,fields=positions)
'positions' is not defined
And if i look into the api the code for the get_account() function looks like:
class Fields(Enum):
'''Account fields passed to :meth:`get_account` and
:meth:`get_accounts`'''
POSITIONS = 'positions'
ORDERS = 'orders'
def get_account(self, account_id, *, fields=None):
fields = self.convert_enum_iterable(fields, self.Account.Fields)
params = {}
if fields:
params['fields'] = ','.join(fields)
Most likely not the correct way to go about this but I found a fix for now.
I commented out the following that checks for the type in the utils.py file for the tda package.
def convert_enum_iterable(self, iterable, required_enum_type):
if iterable is None:
return None
if isinstance(iterable, required_enum_type):
return [iterable.value]
values = []
for value in iterable:
if isinstance(value, required_enum_type):
values.append(value.value)
# elif self.enforce_enums:
# self.type_error(value, required_enum_type)
else:
values.append(value)
return values
I believe if you create your own client you can set this property to false as well.
And then I am able to use the following to get my current positions:
data = client.get_account(config.account_id,fields=['positions'])
At one point, I had these working but haven't tried in a while. I do recall it being difficult to decipher what a field type was. Depending on your import statements, you might need the entire tda.client.Client.Account.Fields.POSITIONS, for example.
r_acct_orders = client.get_account(config.ACCOUNT_ID, fields=tda.client.Client.Account.Fields.ORDERS).json() # field options None, ORDERS, POSITIONS
r = client.get_account(config.ACCOUNT_ID, fields=tda.client.Client.Account.Fields.POSITIONS).json() # field options None, ORDERS, POSITIONS
r = client.get_accounts(fields=tda.client.Client.Account.Fields.ORDERS).json() # field options None, ORDERS, POSITIONS
r = client.get_accounts(fields=None).json() # field options None, ORDERS, POSITIONS
Also, I use a config.py for account_id but you can just use your syntax as needed.
I want to get all of objects that are related to an instance of models.
Because my code is kinda generic, I pass the related table as an string and use eval() function to convert it to the related table class. But I got an error.
Suppose that we have an instance of a table like self.casefile; this is a part of my code:
def related_models_migration(self):
opts = self.casefile._meta
table_name = 'Files'
for f in opts.many_to_many:
name = ''.join(f.name.split('_'))
table_name += name.capitalize()
objects = self.casefile.eval(table_name).all()
and I got this error:
AttributeError Traceback (most recent call last)
<ipython-input-6-025484eeba97> in <module>
----> 1 obj.related_models_migration()
~/Documents/kangaroo/etl/data_migration.py in related_models_migration(self)
28 name = ''.join(f.name.split('_'))
29 table_name += name.capitalize()
---> 30 objects = self.casefile.eval(table_name).all()
31
32 for d in dir(etl.models):
AttributeError: 'FilesCasefiles' object has no attribute 'eval'
How can I pass the class name?
You can not use eval(..) for that. What you probably want to use here is getattr(..):
def related_models_migration(self):
opts = self.casefile._meta
table_name = 'Files'
for f in opts.many_to_many:
name = ''.join(f.name.split('_'))
table_name += name.capitalize()
objects = getattr(self.casefile, table_name).all()
I am not sure you should use table_name += … here however, since it will each time add more content to the table_name. You likely want to use something like table_name = 'Files{}'.format(name.capitalize()).
Note: normally related fields are not capitalized. One writes users or user_set, not Users.
Django provides a way to do this, although you do need to specify the name of the app in which the moodel is defined (because it's possible to have two models with the same name in different apps).
apps.get_model(app_label, model_name, require_ready=True)¶
Returns the Model with the given app_label and model_name.
As a shortcut, this method also accepts a single argument in the form
app_label.model_name. model_name is case-insensitive.
I use flask, an api and SQLAlchemy with SQLite.
I begin in python and flask and i have problem with the list.
My application work, now i try a news functions.
I need to know if my json informations are in my db.
The function find_current_project_team() get information in the API.
def find_current_project_team():
headers = {"Authorization" : "bearer "+session['token_info']['access_token']}
user = requests.get("https://my.api.com/users/xxxx/", headers = headers)
user = user.json()
ids = [x['id'] for x in user]
return(ids)
I use ids = [x['id'] for x in user] (is the same that) :
ids = []
for x in user:
ids.append(x['id'])
To get ids information. Ids information are id in the api, and i need it.
I have this result :
[2766233, 2766237, 2766256]
I want to check the values ONE by One in my database.
If the values doesn't exist, i want to add it.
If one or all values exists, I want to check and return "impossible sorry, the ids already exists".
For that I write a new function:
def test():
test = find_current_project_team()
for find_team in test:
find_team_db = User.query.filter_by(
login=session['login'], project_session=test
).first()
I have absolutely no idea to how check values one by one.
If someone can help me, thanks you :)
Actually I have this error :
sqlalchemy.exc.InterfaceError: (InterfaceError) Error binding
parameter 1 - probably unsupported type. 'SELECT user.id AS user_id,
user.login AS user_login, user.project_session AS user_project_session
\nFROM user \nWHERE user.login = ? AND user.project_session = ?\n
LIMIT ? OFFSET ?' ('my_tab_login', [2766233, 2766237, 2766256], 1, 0)
It looks to me like you are passing the list directly into the database query:
def test():
test = find_current_project_team()
for find_team in test:
find_team_db = User.query.filter_by(login=session['login'], project_session=test).first()
Instead, you should pass in the ID only:
def test():
test = find_current_project_team()
for find_team in test:
find_team_db = User.query.filter_by(login=session['login'], project_session=find_team).first()
Asides that, I think you can do better with the naming conventions though:
def test():
project_teams = find_current_project_team()
for project_team in project_teams:
project_team_result = User.query.filter_by(login=session['login'], project_session=project_team).first()
All works thanks
My code :
project_teams = find_current_project_team()
for project_team in project_teams:
project_team_result = User.query.filter_by(project_session=project_team).first()
print(project_team_result)
if project_team_result is not None:
print("not none")
else:
project_team_result = User(login=session['login'], project_session=project_team)
db.session.add(project_team_result)
db.session.commit()
Here I have a mistake that I can't find the solution. Please excuse me for the quality of the code, I didn't start classes until 6 months ago. I've tried to detach category objects with expunge but once it's added it doesn't work.I was thinking when detaching the object with expunge it will work. and I can't find a solution :( . I pasted as much code as I could so you could see
Traceback (most recent call last):
File "/home/scwall/PycharmProjects/purebeurre/recovery.py", line 171, in <module>
connection.connect.add(article)
File "/home/scwall/PycharmProjects/purebeurre/venv/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 1776, in add
self._save_or_update_state(state)
File "/home/scwall/PycharmProjects/purebeurre/venv/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 1796, in _save_or_update_state
self._save_or_update_impl(st_)
File "/home/scwall/PycharmProjects/purebeurre/venv/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 2101, in _save_or_update_impl
self._update_impl(state)
File "/home/scwall/PycharmProjects/purebeurre/venv/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 2090, in _update_impl
self.identity_map.add(state)
File "/home/scwall/PycharmProjects/purebeurre/venv/lib/python3.6/site-packages/sqlalchemy/orm/identity.py", line 149, in add
orm_util.state_str(state), state.key))
sqlalchemy.exc.InvalidRequestError: Can't attach instance <Categories at 0x7fe8d8000e48>; another instance with key (<class 'packages.databases.models.Categories'>, (26,), None) is already present in this session.
Process finished with exit code 1
class CategoriesQuery(ConnectionQuery):
#classmethod
def get_categories_by_tags(cls, tags_list):
return cls.connection.connect.query(Categories).filter(Categories.id_category.in_(tags_list)).all()
other file:
def function_recovery_and_push(link_page):
count_and_end_page_return_all = {}
count_f = 0
total_count_f = 0
list_article = []
try:
products_dic = requests.get(link_page).json()
if products_dic['count']:
count_f = products_dic['page_size']
if products_dic['count']:
total_count_f = products_dic['count']
if not products_dic['products']:
count_and_end_page_return_all['count'] = False
count_and_end_page_return_all['total_count'] = False
count_and_end_page_return_all['final_page'] = True
else:
count_and_end_page_return_all['final_page'] = False
for product in products_dic["products"]:
if 'nutrition_grades' in product.keys() \
and 'product_name_fr' in product.keys() \
and 'categories_tags' in product.keys() \
and 1 <= len(product['product_name_fr']) <= 100:
try:
list_article.append(
Products(name=product['product_name_fr'], description=product['ingredients_text_fr'],
nutrition_grade=product['nutrition_grades'], shop=product['stores'],
link_http=product['url'],
categories=CategoriesQuery.get_categories_by_tags(product['categories_tags'])))
except KeyError:
continue
count_and_end_page_return_all['count'] = count_f
count_and_end_page_return_all['total_count'] = total_count_f
list_article.append(count_and_end_page_return_all)
return list_article
except:
count_and_end_page_return_all['count'] = False
count_and_end_page_return_all['total_count'] = False
count_and_end_page_return_all['final_page'] = True
list_article.append(count_and_end_page_return_all)
return list_article
p = Pool()
articles_list_all_pool = p.map(function_recovery_and_push, list_page_for_pool)
p.close()
for articles_list_pool in articles_list_all_pool:
for article in articles_list_pool:
if type(article) is dict:
if article['count'] != False and article['total_count'] != False:
count += article['count']
total_count = article['total_count']
if article['final_page'] is True:
final_page = article['final_page']
else:
connection.connect.add(article)
I receive this as an error message, thank you in advance for your answers
This error happens when you try to add an object to a session but it is already loaded.
The only line that I see you use .add function is at the end where you run:
connection.connect.add(article)
So my guess is that this Model is already loaded in the session and you don't need to add it again. You can add a try, except and rollback the operation if it throws an exception.
Had the same issue, not sure you implemented the models as same as I did, but in my case at least, I had in the table's model - i.e:
product_items = relationship(...)
So later when I tried to do
products = session.query(Products).all()
one_of_the_products = products[0]
new_product = ProductItem(product_id=one_of_the_products.id, name='foo', category='bla')
session.add(new_product)
It raises the same exception as you:
sqlalchemy.exc.InvalidRequestError: Can't attach instance <ProductItem at 0x7fe8d8000e48>; another instance with key (<class 'packages.databases.models.ProductItem'>, (26,), None) is already present in this session.
The reason for the exception, is that when I queried for products - the relationship created it's own sub-query and attached the product_item's objects, it placed them in the variable name I defined in the relationship() -> product_items.
So instead of doing:
session_add(new_product)
I just had to use the relationship:
one_of_the_products.product_items.append(new_product)
session.commit()
hope it helps others.
unloading all objects from session and then adding it again in session might help.
db.session.expunge_all()
db.session.add()
I got the following error message:
$ python tmp2.py
why??
Traceback (most recent call last):
File "tmp2.py", line 15, in <module>
test._id = ObjectId(i[0])
File "/home/mictadlo/.virtualenvs/unisnp/lib/python2.7/site-packages/bson/objectid.py", line 92, in __init__
self.__validate(oid)
File "/home/mictadlo/.virtualenvs/unisnp/lib/python2.7/site-packages/bson/objectid.py", line 199, in __validate
raise InvalidId("%s is not a valid ObjectId" % oid)
bson.errors.InvalidId: test1 is not a valid ObjectId
with this code:
from bson.objectid import ObjectId
from mongoengine import *
class Test(Document):
_id = ObjectIdField(required=True)
tag = StringField(required=True)
if __name__ == "__main__":
connect('dbtest2')
print "why??"
for i in [('test1', "a"), ('test2', "b"), ('test3', "c")]:
test = Test()
test._id = ObjectId(i[0])
test.char = i[1]
test.save()
How is it possible to use its own ids which are unique too?
According to the documentation: http://docs.mongoengine.org/apireference.html#fields, ObjectIdField is 'A field wrapper around MongoDB’s ObjectIds.'. So it cannot accept a string test1 as an object id.
You may have to change the code to something like this:
for i in [(bson.objectid.ObjectId('test1'), "a"), (bson.objectid.ObjectId('test2'), "b"), (bson.objectid.ObjectId('test3'), "c")]:
for your code to work (Assuming test1 etc are valid id)
Two things:
ObjectId receives a 24 hex string, you can't initialize it with that string. For instance, instead of using 'test1' you can use a string such as '53f6b9bac96be76a920e0799' or '111111111111111111111111'. You don't even need to initialize an ObjectId, you could do something like this:
...
test._id = '53f6b9bac96be76a920e0799'
test.save()
...
I don't know what are you trying to accomplish by using _id. If you are trying to produce and id field or "primary key" for you document, it's not necessary because one is generated automatically. Your code would be:
class Test(Document):
tag = StringField(required=True)
for i in [("a"), ("b"), ("c")]:
test = Test()
test.char = i[0]
test.save()
print(test.id) # would print something similar to 53f6b9bac96be76a920e0799
If you insist in using a field named _id you must know that your id will be the same, because internally, MongoDB calls it _id. If you still want to use string1 as identifier you should do:
class Test(Document):
_id = StringField(primary_key=True)
tag = StringField(required=True)