1
0
mirror of https://github.com/django/django.git synced 2025-10-26 15:16:09 +00:00

Fixed #251 -- Added OR support to queries, via the new 'complex' DB API keyword argument. Updated docs and added unit tests. Also removed old, undocumented '_or' parameter. Thanks, Hugo.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@1508 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty
2005-11-30 06:14:05 +00:00
parent 837435a08a
commit 9541d7a7c7
5 changed files with 182 additions and 8 deletions

View File

@@ -282,6 +282,81 @@ class RelatedObject(object):
rel_obj_name = '%s_%s' % (self.opts.app_label, rel_obj_name)
return rel_obj_name
class QBase:
"Base class for QAnd and QOr"
def __init__(self, *args):
self.args = args
def __repr__(self):
return '(%s)' % self.operator.join([repr(el) for el in self.args])
def get_sql(self, opts, table_count):
tables, join_where, where, params = [], [], [], []
for val in self.args:
tables2, join_where2, where2, params2, table_count = val.get_sql(opts, table_count)
tables.extend(tables2)
join_where.extend(join_where2)
where.extend(where2)
params.extend(params2)
return tables, join_where, ['(%s)' % self.operator.join(where)], params, table_count
class QAnd(QBase):
"Encapsulates a combined query that uses 'AND'."
operator = ' AND '
def __or__(self, other):
if isinstance(other, (QAnd, QOr, Q)):
return QOr(self, other)
else:
raise TypeError, other
def __and__(self, other):
if isinstance(other, QAnd):
return QAnd(*(self.args+other.args))
elif isinstance(other, (Q, QOr)):
return QAnd(*(self.args+(other,)))
else:
raise TypeError, other
class QOr(QBase):
"Encapsulates a combined query that uses 'OR'."
operator = ' OR '
def __and__(self, other):
if isinstance(other, (QAnd, QOr, Q)):
return QAnd(self, other)
else:
raise TypeError, other
def __or__(self, other):
if isinstance(other, QOr):
return QOr(*(self.args+other.args))
elif isinstance(other, (Q, QAnd)):
return QOr(*(self.args+(other,)))
else:
raise TypeError, other
class Q:
"Encapsulates queries for the 'complex' parameter to Django API functions."
def __init__(self, **kwargs):
self.kwargs = kwargs
def __repr__(self):
return 'Q%r' % self.kwargs
def __and__(self, other):
if isinstance(other, (Q, QAnd, QOr)):
return QAnd(self, other)
else:
raise TypeError, other
def __or__(self, other):
if isinstance(other, (Q, QAnd, QOr)):
return QOr(self, other)
else:
raise TypeError, other
def get_sql(self, opts, table_count):
return _parse_lookup(self.kwargs.items(), opts, table_count)
class Options:
def __init__(self, module_name='', verbose_name='', verbose_name_plural='', db_table='',
fields=None, ordering=None, unique_together=None, admin=None, has_related_links=False,
@@ -1390,6 +1465,13 @@ def _parse_lookup(kwarg_items, opts, table_count=0):
continue
if kwarg_value is None:
continue
if kwarg == 'complex':
tables2, join_where2, where2, params2, table_count = kwarg_value.get_sql(opts, table_count)
tables.extend(tables2)
join_where.extend(join_where2)
where.extend(where2)
params.extend(params2)
continue
if kwarg == '_or':
for val in kwarg_value:
tables2, join_where2, where2, params2, table_count = _parse_lookup(val, opts, table_count)