Programmatic access to SQLModel class attributes - plotly-dash

I am trying to plug a SQLModel table onto a dash data table, handling pagination, filtering and page count in the backend, as explained here https://dash.plotly.com/datatable/callbacks
Working code
from sqlmodel import SQLModel
from sqlmodel import select
from sqlmodel import col
from sqlmodel import Session
from typing import Dict
from typing import List
from typing import Tuple
class Foo(SQLModel, table=True):
bara: str
barb: int
filters = {'bara': ('contains ', 'toto'), 'barb': ('>', 1)}
def filter_foos(filters: Dict[str, Tuple[str, str]]):
"""
try to filter foos
"""
query = select(Foo)
if values := filters.get('bara'):
query = query.where(col(Foo.bara).contains(values[1]))
if values := filters.get('barb'):
if values[0] == '>=':
query = query.where(col(Foo.barb) >= values[1])
elif values[0] == '<=':
query = query.where(col(Foo.barb) <= values[1])
elif values[0] == '!=':
query = query.where(col(Foo.barb) != values[1])
elif values[0] == '=':
query = query.where(col(Foo.barb) == values[1])
elif values[0] == '>':
query = query.where(col(Foo.barb) > values[1])
elif values[0] == '<':
query = query.where(col(Foo.barb) < values[1])
return query
def select_relevant_db_lines(
session: Session,
limit: int,
offset: int,
filters: Dict[str, Tuple[str, str]]
) -> List:
"""
Select relevant row lines from Foo.
"""
if limit is not None and offset is not None:
return list(session.exec(filter_foos(filters).offset(offset*limit).limit(limit)))
My issue is that the filter function is awefully ugly, and not modular at all. If I have an new class
class Fooo(SQLModel, table=True):
toto: str
titi: int
tutu: int
I will hand up redoing the same filter_foos boiler plate code
What I would like would be to have a dictionary to access Foo class attributes, something like (pseudo-code, does not wok)
foo_attributes: Dict = {
'bara': Foo.bara
'barb': Foo.barb
}
That way I can dissociate the generic str int datetime and whatnot treatment and then map them on class attributes. Something like (pseudo-code, not working)
def filter_ints(query, model_field: ???, operator: str, value: int):
"""
try to filter ints
"""
if not operator or not value:
return query
if operator == '>=':
query = query.where(col(model_field) >= value)
elif operator == '<=':
query = query.where(col(model_field) <= value)
elif operator == '!=':
query = query.where(col(model_field) != value)
elif operator == '=':
query = query.where(col(model_field) == value)
elif operator == '>':
query = query.where(col(model_field) > value)
elif operator == '<':
query = query.where(col(model_field) < value)
return query
def filter_strs(query, model_field: ???, value: int):
"""
try to filter strs
"""
if not value:
return query
query = query.where(col(model_field).contains(value))
def filter_models(model: Any, filters: Dict[str, Tuple[str, str]]):
"""
try to filter any model
"""
query = select(model)
if not filters:
return query
for key, (operator, value) in filters:
update_query(query, model, key, operator, value)
Is it possible to do such a thing, or will I have to implement one ugly method after another each time I add a new table to show in my dash app?

Related

Get row and column when checkbox clicked in QtableView

I have a QtableView with data from a file. I added 3 columns with checkboxes, but now I need to know what checkbox is clicked (Row, column, data). This is working for the cell itself but when clicking the checkbox it gives the latest data or if no data it's -1 and None.
I tried to remove a lot of code so I hope this is not to much or to less.
self.model = TableModel([headers, newRows])
self.proxy_model.setSourceModel(self.model)
self.tableView.setModel(self.proxy_model)
self.tableView.clicked.connect(self.cellClicked)
def cellClicked(self):
try:
index = self.tableView.selectionModel().currentIndex()
row = index.row()
col = index.column()
data = index.data()
# print(index.sibling(row,col).data())
if isinstance(data, QtWidgets.QCheckBox):
print(f'Child: {index.child.row()}')
data = data.text()
print(data.isChecked())
print(f'Row:\t{row}\nColumn:\t{col}\nData:\t{data}\n')
except Exception as e:
print(e)
class TableModel(QAbstractTableModel):
def __init__(self, data):
super().__init__()
self.checks = {}
self.headers = data[0]
self.rows = data[1]
def data(self, index, role):
try:
if role == Qt.ItemDataRole.DisplayRole or role == Qt.ItemDataRole.EditRole:
return self.rows[index.row()][index.column()]
elif role == Qt.ItemDataRole.CheckStateRole and (index.column() == 0 or index.column() == 6 or index.column() == 7):
return self.checkState(QPersistentModelIndex(index))
def setData(self, index, value, role = Qt.ItemDataRole.EditRole):
if value is not None and role == Qt.ItemDataRole.EditRole:
self.rows[index.row()][index.column()] = value
# self.dataChanged.emit(index, index)
return True
elif not index.isValid():
return False
elif role == Qt.ItemDataRole.CheckStateRole:
self.checks[QPersistentModelIndex(index)] = value
return True
return False
def checkState(self, index):
if index in self.checks.keys():
return self.checks[index]
else:
return Qt.CheckState.Unchecked
def flags(self, index):
col = index.column()
if col == 0 or col == 6 or col == 7:
return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsEditable | Qt.ItemFlag.ItemIsUserCheckable
else:
return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEditable

doing a search of the database python/flask no sql

I am trying to get a search function working. I have a database using excel and would like to be able to search it while on the go. I am stuck trying to get the search form working. Below is the code in python for the form:
from forms import ComicSearchForm
#app.route('/make_search', methods=['GET', 'POST'])
def search():
search = ComicSearchForm(request.form)
if request.method == 'GET, POST':
return search_results(result)
return render_template('search.html', form=search)
#app.route('/search')
# #login required
def search_results(result):
bob = create_bob('*', '*', '*', '*', '*', '*')
bobby = []
current_page = request.args.get('page', 1, type=int)
per_page = 10
end = (current_page * per_page) + 1
if end > len(bob):
end = len(bob)
start = ((current_page - 1) * per_page) + 1
sort_bob = sorted(bob, key=lambda v: (v.issue_type, v.publisher, v.sort, v.character, v.volume, v.issues,
v.publication_date))
if datetime.strptime(sort_bob[0][7], '%B, %Y') >= datetime.now():
sort_bob = sorted(sort_bob, key=lambda v: (v.publication_date, '%B, %Y'))
for result in bob[start:end]:
if result.bob.series_title == str.find(''):
bobby.append(result)
next = str(current_page + 1) if end < len(bob) else '0'
prev = str(current_page - 1)
if not result:
flash('No results found!')
return redirect('make_search')
else:
# display results
return render_template('search.html', bobby=bobby, header=original_header, next=next, prev=prev)
Here is the form:
from wtforms import Form, StringField, SelectField
class ComicSearchForm(Form):
choices = [('Series Title', 'Series Title'),
('Author', 'Author'),
('Artist', 'Artist'),
('Publisher', 'Publisher'),
('Publication Date', 'Publication Date')]
select = SelectField('Search for comics:', choices=choices)
search = StringField('')
I am stuck trying to figure out:
for result in bob[start:end]:
if result.bob.series_title == str.find(''):
bobby.append(result)
This is where i am currently think this needs work. I would love some ideas of where i need to go to make this work.
Thanks,
Zach

dictionary value is dict but printing as string in json dump

I have a script that is working fine except for this tiny issue. My script is looping over list items and appending a json string over a loop and then doing json dump to file.
My json string:
main_json = {"customer": {"main_address": "","billing_address": "","invoice_reference": "","product": []}}
main loop:
for row in result:
account_id = ACCOUNTID_DATA_CACHE.get(row['customer.main_address.customer_id'])
if account_id is None or account_id != row['customer.main_address.customer_id']:
if main_json:
results.append(main_json)
main_json = {"customer": {"main_address": "","billing_address": "","invoice_reference": "","product": []}}
main_address = {}
billing_address = {}
for key,value in row.items():
if key.startswith('customer.main_address'):
main_address[key.split(".")[2]] = value
if key.startswith('customer.billing_address'):
billing_address[key.split(".")[2]] = value
billing_address_copy = billing_address.copy()
for mkey,mvalue in main_address.items():
for bkey,bvalue in billing_address_copy.items():
if str(bvalue) == str(mvalue):
bvalue = ''
billing_address_copy[bkey] = bvalue
if all(value == '' for value in billing_address_copy.values()) is True:
main_json['customer']['billing_address'] = ''
else:
main_json['customer']['billing_address'] = billing_address
main_json['customer']['main_address'] = main_address
product = parse_products(row)
main_json['customer']['product'].append(product)
...
def parse_products(row):
product = {}
x = {}
for key,value in row.items():
if key.startswith('customer.product'):
product[key.split(".")[2]] = value
if key.startswith('customer.product.custom_attributes'):
x['domain'] = value
print(x)
product[key.split(".")[2]] = x
if key == 'start_date' or 'renewal_date':
value = str(value)
product[key] = value
return product
In this part below, how do make sure that the value is not a string when dumped?
if key.startswith('customer.product.custom_attributes'):
x['domain'] = value
print(x)
product[key.split(".")[2]] = x
Because in the output I'm getting:
{
"custom_attributes": "{'domain': 'somedomain.com'}",
"description": "some_description",
"discount": "0.00"}
When what I really want is:
{
"custom_attributes": {"domain": "somedomain.com"},
"description": "some_description",
"discount": "0.00"}
EDIT: how i'm dumping:
with open('out.json', 'w') as jsonout:
json.dump(main_json, jsonout, sort_keys=True, indent=4)
Well, this IF is flawed and always TRUE:
if key == 'start_date' or 'renewal_date':
So you are converting everything to str()

adding functions to self made calculator

Ok so I'm trying to make a working napier numeral calculator. I have gone through most of the steps I need to make it work. I need 2 more steps the function and converting it back to napier numbers. Currently I'm stuck on getting the functions to work. It just seems to skip that step. From what I can tell it should work and not be skipped. Could anyone tell me if I missed a step in the process of making the function.
def main():
response = 'y'
while response == 'y' or response == 'Y':
nap1 = getNapier()
num1 = napToInt(nap1)
print(num1)
nap2 = getNapier()
num2 = napToInt(nap2)
print(num1, num2)
operator = getOperator
result = doMath(num1, num2, operator)
response = input("Try another[y/n]")
def doMath(num1, num2, operator):
if operator == "+":
answer = num1 + num2
elif operator == "-":
answer = num1 - num2
elif operator == "*":
answer = num1 * num2
else:
if operator == "/":
answer = num1 / num2
return doMath
def getOperator():
op = input("Enter operator: ")
while op not in "+-*/":
op = input("Error!!!! Enter operator: ")
return op
def napToInt(n):
result = 0
for ch in n:
result += 2 ** (ord(ch) - ord('a'))
return result
def getNapier():
nap = input("Enter Napier number: ")
while not nap.isalpha():
nap = input("Error!!! Enter Napier number: ")
return nap
main()
this is the result I get as you can see it gets the napier numbers and just stops
Enter Napier number: asdf
262185
Enter Napier number: adsf
262185 262185
Try another[y/n]
your line operator = getOperator should be operator = getOperator()

python function will not return value that is based on condition

I am new to this, and I am looking for help. I currently am stuck in a program I'm trying to complete. Here it is:
def printStock(stockList, stockPrice, p):
for i in range(len(stockPrice)):
if stockPrice[i] > p:
p = stockList[i]
print("The stocks with a higher value are:", p)
def searchStock(stockList, stockPrice, s):
for i in range(len(stockList)):
if s == stockList[i]:
s = stockPrice[i]
elif s != stockList[i]:
s = -1
return s
def mainFun():
stockList= []
stockPrice = []
l = 1
while l > 0:
stocks = str(input("Enter the name of the stock:"))
stockList += [stocks]
if stocks == "done"or stocks == 'done':
l = l * -1
stockList.remove("done")
else:
price = int(input("Enter the price of the stock:"))
stockPrice += [price]
l = l + 1
print(stockList)
print(stockPrice)
s = input("Enter the name of the stock you're looking for:")
searchStock(stockList, stockPrice, s)
p = s
printStock(stockList, stockPrice, p)
Every time I run the program to the end, it never returns the variable s for some reason. If i replace return with print, it always prints -1 instead of the stockPrice if its on the list. I also get an error saying "unorderable types int() > str()" regarding line 3. Basically the function printStock takes the three parameters and once the function is done it should print the names of the stocks higher than the value 'p'. The value of 'p' is the same as the value I get after calling searchStock function, but I cant seem to get it to work. Can someone please help me?
s is being returned from the function, but the return value is not being assigned to any variable on the outer scope.
Just replace
searchStock(stockList, stockPrice, s)
with
s=searchStock(stockList, stockPrice, s)
And everything should work as expected