Ticket #980: orm_queries.2.py

File orm_queries.2.py, 6.5 KB (added by brantley (deadwisdom@…, 19 years ago)

Query system examples (No spaces, sorry!)

Line 
1class Model(object):
2 def __init__(self, table_name):
3 self.table_name = table_name
4
5 def query(self, *result):
6 return Query(self.table_name, result)
7
8class Query(object):
9 def __init__(self, table, clauses=None):
10 if (clauses):
11 self.object = WhereAnd(clauses)
12 else:
13 self.object = None
14
15 self.results = None
16 self.len = None
17 self.table = table
18 self.parent = None
19
20 def __iadd__(self, other):
21 "Results from self += other"
22 assert self.table == other.table, "Table mismatch in queries."
23 assert self.parent == other.parent, "Parent mismatch in queries. They both aren't subqueries of the same query."
24 self.object = WhereOr((self.object, other.object))
25 self.results = None # Since we're modifying this, delete our caches
26 self.len = None
27 return self
28
29 def __add__(self, other):
30 "Results from (self + other)"
31 assert self.table == other.table, "Table mismatch in queries."
32 assert self.parent == other.parent, "Parent mismatch in queries. They both aren't subqueries of the same query."
33 q = Query(self.table)
34 q.object = WhereOr((self.object, other.object))
35 q.parent = self.parent
36 return q
37
38 def _get_final_object(self):
39 "Resovles the final object in case this Query has a parent (is a sub-query)."
40 if (self.parent == None):
41 return self.object
42 else:
43 return WhereAnd((self.object, self.parent.object))
44
45 def fetch(self):
46 "Hits the database, and returns the results"
47 print "SELECT * FROM `%s` WHERE %r" % (self.table, self._get_final_object())
48 self.results = ["Bob"] # Since we don't actually have a database, return Bob.
49 return self.results
50
51 def _count(self):
52 "If we don't actually use the results, and just need the length, this optimizes it a bit."
53 print "SELECT COUNT(*) FROM `%s` WHERE %r" % (self.table, self._get_final_object())
54 self.len = 1
55
56 def sub_query(self, *clauses):
57 "Creates a sub-query, all results in that query come from the results of this."
58 q = Query(self.table, clauses)
59 q.parent = self
60 return q
61
62 def __iter__(self):
63 "Container emulation"
64 if (self.results == None):
65 self.fetch()
66 return self.results.__iter__()
67
68 def __len__(self):
69 "Container emulation"
70 if (self.results): # If we have results, return the length of those
71 return len(self.results)
72 elif (self.len == None): # If we don't have a cache of the length, query the database
73 self._count()
74 return self.len # We must have a cache of the length, so return that.
75
76 def __getitem__(self, i):
77 "Container emulation"
78 if (self.results == None):
79 self.fetch()
80 return self.results[i]
81
82 def __contains__(self, o):
83 "Container emulation | i.e. if (o in self):"
84 if (self.results == None):
85 self.fetch()
86 return o in self.results
87
88 def __str__(self):
89 "Container emulation | print self"
90 if (self.results):
91 return str(self.results)
92 else:
93 return str(self.fetch())
94
95class WhereOr(object):
96 "OR clause"
97 def __init__(self, clauses):
98 self.clauses = clauses
99
100 def __repr__(self):
101 return "(%s)" % " OR ".join([repr(c) for c in self.clauses])
102
103class WhereAnd(object):
104 "AND clause"
105 def __init__(self, clauses):
106 self.clauses = clauses
107
108 def __repr__(self):
109 return "(%s)" % " AND ".join([repr(c) for c in self.clauses])
110
111class WhereClause(object):
112 "Operator clause | i.e. field < value"
113 def __init__(self, *args):
114 self.args = args
115
116 def __repr__(self):
117 return "%s %s %r" % self.args
118
119class Field(object):
120 def __init__(self, name):
121 self.name = name
122
123 def __lt__(self, other):
124 return WhereClause(self.name, "<", other)
125
126 def __gt__(self, other):
127 return WhereClause(self.name, ">", other)
128
129 def __eq__(self, other):
130 return WhereClause(self.name, "=", other)
131
132 def __ne__(self, other):
133 return WhereClause(self.name, "<>", other)
134
135 def __le__(self, other):
136 return WhereClause(self.name, "<=", other)
137
138 def __ge__(self, other):
139 return WhereClause(self.name, ">=", other)
140
141 def contains(self, other):
142 return WhereClause(self.name, "LIKE", "%%%s%%" % other)
143
144 def startswith(self, other):
145 return WhereClause(self.name, "LIKE", "%s%%" % other)
146
147 def endswith(self, other):
148 return WhereClause(self.name, "LIKE", "%%%s" % other)
149
150class FieldFactory(object):
151 def __getattr__(self, k):
152 return Field(k)
153
154 def __getitem__(self, i):
155 return Field(i)
156
157# These would be imported, as in:
158# django.models.app import polls, choices
159# django.database import field
160field = FieldFactory()
161polls = Model('polls')
162choices = Model('choices')
163
164
165# The results will always be ['Bob'], because we aren't actually talking to a database.
166
167# Basic union:
168results = choices.query(field.choice == 'A choice')
169results += choices.query(field.votes > 4)
170print results[0] # Database hit
171
172# Sub-query:
173results = choices.query(field.choice == 'A choice')
174popular_choices = results.sub_query(field.votes > 10)
175print popular_choices # Database hit
176
177# Equivelant to the Sub-query
178popular_choices = choices.query(field.choice == 'A choice', field.votes > 10)
179print popular_choices # Database hit
180
181# LIKE / Startswith
182obstaining = choices.query(field.choice.startswith("I don't know"))
183print obstaining
184
185# Never called
186never_results = choices.query(field.choice == 'There is never results, cause I am never used.')
187
188# Fetched
189results = choices.query(field.choice == 'A choice')
190results.fetch() # Database hit
191print results # Cache used
192
193# Only counted
194results = choices.query(field.choice == 'A choice')
195print len(results) # Database hit, but only with a count
196
197# Uncomment to create an Assertion error, because we're adding two different table results
198#results = polls.query(field.question == 'Love to error out!')
199#results += choices.query(field.choice == 'A choice and a question? Throw Assertion!')
200
Back to Top