dynamic query sorting with Peewee - python

I'm having trouble assembling dynamic sorting with my Peewee python app.
Catalog is a Model object from playhouse.signals
Database is MariaDB
I can sort by 2 fields like this:
resultset = Catalog.select().where(...).order_by(Catalog.app_team,Catalog.domain)
I can use a dynamic sort field like this:
sortlist = []
opt = 'domain'
sortlist.append(getattr(Catalog,opt))
resultset = Catalog.select().where(...).order_by(sortlist)
But I can't see how to do more than one dynamic field. It fails if I pass it a list of 2 objects.
I tried passing a string like 'Catalog.app_team,Catalog.domain' but a string is ignored.
Any help is much appreciated.

Related

Dynamically set columns to filter with ORM in SQLAlchemy

I cannot figure out how to set columns dynamically for filtering using the latest SQLalchemy style for ORM.
Basically, I want to create a wrapper function to be able to pass in any columns into the 'where' part of the statement, the idea would be:
def get_id(column, value):
id = session.execute(select(Account.id).where(
Account.column == value)).all()
return id
My problem is that I cannot dynamically select the attribute of the Account object with Account[column] as I get the error: TypeError: 'DeclarativeMeta' object is not subscriptable
I know this is possible with Core by setting up table MetaData and using either account.c[column] or the column() function but I would be interested in an ORM solution as my tables are automapped.
Thanks for the help.
Basically, you can use reflection features of Python, like this.
column_name = 'name';
getattr(Account, column_name) # This is equivalent to Account.name
But you can also use a ready-made API like this.
ids = [id for id, in session.query(Account.id).filter_by(**{column_name: value}).all()]
See Query API.

SQLAlchemy getting column data types of view results in MySQL

I've seen a few posts on this but nothing that works for me unfortunately.
Basically trying to get the SQLAlchemy (or pandas) column data types from a list of views in a MySQL database.
import sqlalchemy as sa
view = "myView"
engine = "..."
meta = sa.MetaData(engine, True)
This errors:
tb_data = meta.tables["tb_data"]
# KeyError: 'tb_data'
And I don't know what I'm supposed to do with this:
sa.Table(view, meta).columns
# <sqlalchemy.sql.base.ImmutableColumnCollection at 0x7f9cb264d4a0>
Saw this somewhere but not sure how I'm supposed to use it:
str_columns = filter(lambda column: isinstance(column.type, sa.TEXT), columns)
# <filter at 0x7f9caafab640>
Eventually what I'm trying to achieve is a list or dict of data types for a view that I can then use to load to a PostgreSQL database. Happy to consider alternatives outside of sqlalchemy and/or pandas if they exist (and are relatively trivial to implement).

How to use django ORM to query database

I have a model called 'dboinv_product' and this model has a field called 'product_name'
I need to use Django ORM in my views.py file to pull ALL the product names. The goal is to put it into a list this way I can serialize it using JSON.
Does anyone know which Django command(s) can be used to produce this list?
Essentially, I need the equivalent of "SELECT ALL product_name FROM dbo.inv_product"
values_list is what you are looking for.
value= dboinv_product.objects.values_list('product_name', flat=True)
list = list(value) # to convert to a list
# flat=True to get list rather than tuple inside of the ValuesListQuerySet.
The document about values_listis here. 1

Create SQL database from dict with different features in python

I have the following dict:
base = {}
base['id1'] = {'apple':2, 'banana':4,'coconut':1}
base['id2'] = {'apple':4, 'pear':8}
base['id3'] = {'banana':1, 'tomato':2}
....
base['idN'] = {'pineapple':1}
I want to create a SQL database to store it. I normally use sqlite but here the number of variables (features in the dict) is not the same for all ids and I do not know all of them thus I cannot use the standard procedure.
Does someone know an easy way to do it ?
ids will get duplicated if you use the sql i would suggest use postgres as it has a jsonfield ypu can put your data there corresponding to each key. Assuming you are not constrained to use SQL.

How to efficiently fetch objects after created using bulk_create function of Django ORM?

I have to insert multiple objects in a table, there are two ways to do that-
1) Insert each one using save(). But in this case there will be n sql dB queries for n objects.
2) Insert all of them together using bulk_create(). In this case there will be one sql dB query for n objects.
Clearly, second option is better and hence I am using that. Now the problem with bulk__create is that it does not return ids of the inserted objects hence they can not be used further to create objects of other models which have foreign key to the created objects.
To overcome this, we need to fetch the objects created by bulk_create.
Now the question is "assuming as in my situation, there is no way to uniquely identify the created objects, how do we fetch them?"
Currently I am maintaining a time_stamp to fetch them, something like below-
my_objects = []
# Timestamp to be used for fetching created objects
time_stamp = datetime.datetime.now()
# Creating list of intantiated objects
for obj_data in obj_data_list:
my_objects.append(MyModel(**obj_data))
# Bulk inserting the instantiated objects to dB
MyModel.objects.bulk_create(my_objects)
# Using timestamp to fetch the created objects
MyModel.objects.filter(created_at__gte=time_stamp)
Now this works good, but will fail in one case.
If at the time of bulk-creating these objects, some more objects are created from somewhere else, then those objects will also be fetched in my query, which is not desired.
Can someone come up with a better solution?
As bulk_create will not create the primary keys, you'll have to supply the keys yourself.
This process is simple if you are not using the default generated primary key, which is an AutoField.
If you are sticking with the default, you'll need to wrap your code into an atomic transaction and supply the primary key yourself. This way you'll know what records are inserted.
from django.db import transaction
inserted_ids = []
with transacation.atomic():
my_objects = []
max_id = int(MyModel.objects.latest('pk').pk)
id_count = max_id
for obj_data in obj_data_list:
id_count += 1
obj_data['id'] = id_count
inserted_ids.append(obj_data['id'])
my_objects.append(MyModel(**obj_data))
MyModel.objects.bulk_create(my_objects)
inserted_ids = range(max_id, id_count)
As you already know.
If the model’s primary key is an AutoField it does not retrieve and
set the primary key attribute, as save() does.
The way you're trying to do, it's usually the way people do.
The other solution in some cases, this way is better.
my_ids = MyModel.objects.values_list('id', flat=True)
objs = MyModel.objects.bulk_create(my_objects)
new_objs = MyModel.objects.exclude(id__in=my_ids).values_list('id', flat=True)

Categories

Resources