SQLALchemy: update with in clause from kwargs
dn
PythonList at DancesWithMice.info
Tue Aug 3 22:25:29 EDT 2021
On 04/08/2021 13.08, Larry Martell wrote:
> I am trying to write a function that takes kwargs as a param and
> generates an update statement where the rows to be updated are
> specified in an in clause.
>
> Something like this:
>
> def update_by_in(self, **kwargs):
> filter_group = []
> for col in kwargs['query_params']:
> # obviously this line does not work as col is a string,
> but this is the intent
> filter_group.append(col.in_(tuple(kwargs['query_params'][col])))
>
> self._session.query(self.model_class).filter(*filter_group).update(kwargs['values'])
>
> self.update_by_in(
> **{'query_params': {'companyCode': ['A', 'B', 'C']},
> 'values': {'portfolioName': 'test'}}
> )
>
> Is there a way to do this? I think I need to use setattr in building
> up the filter_group list, but I'm not quite sure how to do it.
When feeling bamboozled by a problem, particularly when using
sophisticated tools such as SQLAlchemy, the trick is often to simplify
the problem.
Step 1 (using the sample data provided)
Write the query on paper - and as constant-values.
Step 2
Compare the two input dicts with that requirement.
Step 3
Work-out the transformation(s) required...
One complexity is that the parameter to update_by_in() is formed by
joining two dicts. However, the function later tries to treat them in
distinct fashions. Why the join/why not two parameters?
companyCode = ['A', 'B', 'C']
values = {'portfolioName': 'test'}
leading to:
self.update_by_in( companyCode, values )
and:
def update_by_in(self, company_code, portfolio_type ):
....
As to the core of the question-asked, I'm a little confused (which may
be my fuzzy head). Do you want the update(s) - portrayed as a list -
like this:
[('A', 'test'), ('B', 'test'), ('C', 'test')]
like this:
[('A', 'portfolioName'), ('B', None), ('C', None)]
or only:
[('A', 'portfolioName')]
You will find a friend in the itertools (PSL) library:
import itertools as it
list( it.product( companyCode, values.values() ) )
[('A', 'test'), ('B', 'test'), ('C', 'test')]
list( it.zip_longest( companyCode, values.values() ) )
[('A', 'test'), ('B', None), ('C', None)]
list( zip( companyCode, values ) )
[('A', 'portfolioName')]
Now, have we simplified things to the point of being able to more-easily
code the update and filter?
PS I fear even that step is/those steps are more complicated than needed
- but you know your data and schema better than I!
Critique:
1 never, never, never(!) use a name which will "shadow" a Python keyword
or frequently-used function-name (in this case "values" ) - if you don't
confuse Python you will confuse simple-boys like me! Plus, when you come
back in six-month's time, does "values" tell you what kind of value it
is/holds?
2 Python != C | Java
Thus: company_code, portfolio_name
Web.Refs:
https://www.dictionary.com/browse/bamboozled
https://docs.python.org/3/library/itertools.html
--
Regards,
=dn
More information about the Python-list
mailing list