mirror of
https://github.com/django/django.git
synced 2025-08-24 20:44:24 +00:00
Fixed #7210 -- Added F() expressions to query language. See the documentation for details on usage.
Many thanks to: * Nicolas Lara, who worked on this feature during the 2008 Google Summer of Code. * Alex Gaynor for his help debugging and fixing a number of issues. * Malcolm Tredinnick for his invaluable review notes. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9792 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
08dd4176ed
commit
cf37e4624a
16 changed files with 586 additions and 48 deletions
110
django/db/models/expressions.py
Normal file
110
django/db/models/expressions.py
Normal file
|
@ -0,0 +1,110 @@
|
|||
from copy import deepcopy
|
||||
from datetime import datetime
|
||||
|
||||
from django.utils import tree
|
||||
|
||||
class ExpressionNode(tree.Node):
|
||||
"""
|
||||
Base class for all query expressions.
|
||||
"""
|
||||
# Arithmetic connectors
|
||||
ADD = '+'
|
||||
SUB = '-'
|
||||
MUL = '*'
|
||||
DIV = '/'
|
||||
MOD = '%%' # This is a quoted % operator - it is quoted
|
||||
# because it can be used in strings that also
|
||||
# have parameter substitution.
|
||||
|
||||
# Bitwise operators
|
||||
AND = '&'
|
||||
OR = '|'
|
||||
|
||||
def __init__(self, children=None, connector=None, negated=False):
|
||||
if children is not None and len(children) > 1 and connector is None:
|
||||
raise TypeError('You have to specify a connector.')
|
||||
super(ExpressionNode, self).__init__(children, connector, negated)
|
||||
|
||||
def _combine(self, other, connector, reversed, node=None):
|
||||
if reversed:
|
||||
obj = ExpressionNode([other], connector)
|
||||
obj.add(node or self, connector)
|
||||
else:
|
||||
obj = node or ExpressionNode([self], connector)
|
||||
obj.add(other, connector)
|
||||
return obj
|
||||
|
||||
###################
|
||||
# VISITOR METHODS #
|
||||
###################
|
||||
|
||||
def prepare(self, evaluator, query, allow_joins):
|
||||
return evaluator.prepare_node(self, query, allow_joins)
|
||||
|
||||
def evaluate(self, evaluator, qn):
|
||||
return evaluator.evaluate_node(self, qn)
|
||||
|
||||
#############
|
||||
# OPERATORS #
|
||||
#############
|
||||
|
||||
def __add__(self, other):
|
||||
return self._combine(other, self.ADD, False)
|
||||
|
||||
def __sub__(self, other):
|
||||
return self._combine(other, self.SUB, False)
|
||||
|
||||
def __mul__(self, other):
|
||||
return self._combine(other, self.MUL, False)
|
||||
|
||||
def __div__(self, other):
|
||||
return self._combine(other, self.DIV, False)
|
||||
|
||||
def __mod__(self, other):
|
||||
return self._combine(other, self.MOD, False)
|
||||
|
||||
def __and__(self, other):
|
||||
return self._combine(other, self.AND, False)
|
||||
|
||||
def __or__(self, other):
|
||||
return self._combine(other, self.OR, False)
|
||||
|
||||
def __radd__(self, other):
|
||||
return self._combine(other, self.ADD, True)
|
||||
|
||||
def __rsub__(self, other):
|
||||
return self._combine(other, self.SUB, True)
|
||||
|
||||
def __rmul__(self, other):
|
||||
return self._combine(other, self.MUL, True)
|
||||
|
||||
def __rdiv__(self, other):
|
||||
return self._combine(other, self.DIV, True)
|
||||
|
||||
def __rmod__(self, other):
|
||||
return self._combine(other, self.MOD, True)
|
||||
|
||||
def __rand__(self, other):
|
||||
return self._combine(other, self.AND, True)
|
||||
|
||||
def __ror__(self, other):
|
||||
return self._combine(other, self.OR, True)
|
||||
|
||||
class F(ExpressionNode):
|
||||
"""
|
||||
An expression representing the value of the given field.
|
||||
"""
|
||||
def __init__(self, name):
|
||||
super(F, self).__init__(None, None, False)
|
||||
self.name = name
|
||||
|
||||
def __deepcopy__(self, memodict):
|
||||
obj = super(F, self).__deepcopy__(memodict)
|
||||
obj.name = self.name
|
||||
return obj
|
||||
|
||||
def prepare(self, evaluator, query, allow_joins):
|
||||
return evaluator.prepare_leaf(self, query, allow_joins)
|
||||
|
||||
def evaluate(self, evaluator, qn):
|
||||
return evaluator.evaluate_leaf(self, qn)
|
Loading…
Add table
Add a link
Reference in a new issue