Query conditions and a couple of nits

3 views
Skip to first unread message

bartmosley

unread,
Apr 15, 2009, 2:58:43 PM4/15/09
to Autumn ORM
This is a great ORM package. I've made a change to make it easier to
use >, <, 'like', etc. in queries--adding a class called
WhereOperators that consists of a number of functions, e.g.

class WhereOperators(object):
'''
Provides the ability to create queries using >,<, !=, etc.
Usage:

Filter = WhereOperators()

say the model MyModel includes a numeric field 'amount'

q = Query(model=MyModel).filter( amount = Filter.gt(100))

returns records where amount > 100
'''
def isnull(self):
return (" is ", None)
def gt(self, value):
return (">", value)

which required modifying the "extract_condition..." functions.


A couple of behaviors were causing me trouble, so modified as follows:

1) >>> q.Query(model=MyModel).filter( first_name = 'bob')
>>> for i in q:
print q.fist_name, q.last_name
bob haskins
bob wills
....
>>> q = q.filter(first_name = 'jane')
>>> for i in q:
print q.fist_name, q.last_name
bob haskins
bob wills

because if Query.cache is not None, you don't re-execute the
query. So I changed Query.filter() to set self.cache to None when
the conditions are updated.

2) say you had:
>>> q = Query(model=MyModel).filter( name = 'bob')
>>> q.count()
20

q is now a "SELECT COUNT(*) " query so
>>> for i in q:
....doing something expecting a MyModel object
gets a bad result

def count(self):
# Old logic changes query, so further calls do not return
model objects.
# I assume behaviour is supposed return table count if no
query
# conditions are entered
self.get_data()
if self.cache is None:
# self.type = 'SELECT COUNT(*)'
# return self.execute_query().fetchone()[0]
return 0
else:
return len(self.cache)

Don't know if you were working on any of these, there might be
(probably are) better solutions than what I've come up with. I can
send you a diff, if you wish.

Bart.

SuperJared

unread,
Apr 26, 2009, 9:05:17 PM4/26/09
to Autumn ORM
Bart,

I was planning to implement such filters in a different fashion, but I
definitely like what you've come up with. Do you have a github
account? The repository is now hosted there so it'll be easier to fork/
merge there.

http://github.com/JaredKuolt/autumn/tree/master

Also, if you could implement tests for them, it'd be much appreciated.

The count method should certainly be cleaned up so it's not so stupid.
If you have a diff for that to work, that's great too. Any additional
test coverage for this case should also be committed (by either you or
me :).

Thanks much!

Bart Mosley, bondgeek.com

unread,
May 1, 2009, 2:10:36 PM5/1/09
to autum...@googlegroups.com
Jared,

Thanks. I should be able to get to this in the next week, once I
finish up a project I'm working on. I'm new to the github, opensource
project thing--but I'll figure it out.

It occurred to me that using staticmethods would make more sense than
having to defining an instance of the filter, so one could type 'age =
Filter.gt(100)' without instantiating--also, I'm going to try to have
it so you can type ' age = Filter.gt('IQ') ' where age and IQ are two
columns in the table.

By the time I'm finished with my current project, I should have some
pretty good test scenarios, too.

Bart.


_________________________
Bart Mosley
President & Founder
BG Research LLC
www.bondgeek.com
ba...@bondgeek.com

bartmosley

unread,
May 2, 2009, 2:14:53 PM5/2/09
to Autumn ORM
I've started a new fork where you'll begin to see the changes. But
first, a new question.

Since Query is passed the argument 'conditions={}' as a default, you
get a potentially confusing behavior:

firstquery = Query(model=MyModel).filter(name="John")
otherquery = Query(model=MyOtherModel).filter(othername="OtherJohn")

firstquery.conditions is now:
{"name": "John", "othername": "OtherJohn"}

This can be fixed by changing the default to conditions=None and the
necessary logic in __init__, but I would suggest having __init__ set
conditions={} explicitly and forcing the user to use filter() to set
conditions. Simpler code and a single way of doing things--creating
a dictionary and passing it to the class initialization seems just as
cumbersome as a 'Query().filter()' call. Also the user can always set
'qry.condition = mydictionary' if they hate the filter method. What do
you think?

p.s. I posted a simple example and discussion of this behaviour at:
http://bgresearch-bondgeek.blogspot.com/2009/05/6.html

On May 1, 2:10 pm, "Bart Mosley, bondgeek.com" <ba...@bondgeek.com>
wrote:
Reply all
Reply to author
Forward
0 new messages