Fixed #23627 -- Allowed register_lookup to work as a decorator.

This commit is contained in:
Marc Tamlyn 2014-10-09 17:04:50 +01:00
parent d6a87eefd8
commit 92a17eaae0
5 changed files with 22 additions and 14 deletions

View File

@ -160,6 +160,7 @@ class ArrayField(Field):
return super(ArrayField, self).formfield(**defaults) return super(ArrayField, self).formfield(**defaults)
@ArrayField.register_lookup
class ArrayContainsLookup(Lookup): class ArrayContainsLookup(Lookup):
lookup_name = 'contains' lookup_name = 'contains'
@ -171,9 +172,7 @@ class ArrayContainsLookup(Lookup):
return '%s @> %s::%s' % (lhs, rhs, type_cast), params return '%s @> %s::%s' % (lhs, rhs, type_cast), params
ArrayField.register_lookup(ArrayContainsLookup) @ArrayField.register_lookup
class ArrayContainedByLookup(Lookup): class ArrayContainedByLookup(Lookup):
lookup_name = 'contained_by' lookup_name = 'contained_by'
@ -184,9 +183,7 @@ class ArrayContainedByLookup(Lookup):
return '%s <@ %s' % (lhs, rhs), params return '%s <@ %s' % (lhs, rhs), params
ArrayField.register_lookup(ArrayContainedByLookup) @ArrayField.register_lookup
class ArrayOverlapLookup(Lookup): class ArrayOverlapLookup(Lookup):
lookup_name = 'overlap' lookup_name = 'overlap'
@ -197,9 +194,7 @@ class ArrayOverlapLookup(Lookup):
return '%s && %s' % (lhs, rhs), params return '%s && %s' % (lhs, rhs), params
ArrayField.register_lookup(ArrayOverlapLookup) @ArrayField.register_lookup
class ArrayLenTransform(Transform): class ArrayLenTransform(Transform):
lookup_name = 'len' lookup_name = 'len'
@ -212,9 +207,6 @@ class ArrayLenTransform(Transform):
return 'array_length(%s, 1)' % lhs, params return 'array_length(%s, 1)' % lhs, params
ArrayField.register_lookup(ArrayLenTransform)
class IndexTransform(Transform): class IndexTransform(Transform):
def __init__(self, index, base_field, *args, **kwargs): def __init__(self, index, base_field, *args, **kwargs):

View File

@ -45,6 +45,7 @@ class RegisterLookupMixin(object):
if 'class_lookups' not in cls.__dict__: if 'class_lookups' not in cls.__dict__:
cls.class_lookups = {} cls.class_lookups = {}
cls.class_lookups[lookup.lookup_name] = lookup cls.class_lookups[lookup.lookup_name] = lookup
return lookup
@classmethod @classmethod
def _unregister_lookup(cls, lookup): def _unregister_lookup(cls, lookup):

View File

@ -46,6 +46,18 @@ it with ``Field`` directly::
from django.db.models.fields import Field from django.db.models.fields import Field
Field.register_lookup(NotEqual) Field.register_lookup(NotEqual)
Lookup registration can also be done using a decorator pattern::
from django.db.models.fields import Field
@Field.registerLookup
class NotEqualLookup(Lookup):
# ...
.. versionchanged:: 1.8
The ability to use the decorator pattern was added.
We can now use ``foo__ne`` for any field ``foo``. You will need to ensure that We can now use ``foo__ne`` for any field ``foo``. You will need to ensure that
this registration happens before you try to create any querysets using it. You this registration happens before you try to create any querysets using it. You
could place the implementation in a ``models.py`` file, or register the lookup could place the implementation in a ``models.py`` file, or register the lookup

View File

@ -299,6 +299,9 @@ Models
* ``extra(select={...})`` now allows you to escape a literal ``%s`` sequence * ``extra(select={...})`` now allows you to escape a literal ``%s`` sequence
using ``%%s``. using ``%%s``.
* :doc:`Custom Lookups</howto/custom-lookups>` can now be registered using
a decorator pattern.
Signals Signals
^^^^^^^ ^^^^^^^

View File

@ -50,6 +50,7 @@ class YearTransform(models.Transform):
return models.IntegerField() return models.IntegerField()
@YearTransform.register_lookup
class YearExact(models.lookups.Lookup): class YearExact(models.lookups.Lookup):
lookup_name = 'exact' lookup_name = 'exact'
@ -66,9 +67,9 @@ class YearExact(models.lookups.Lookup):
return ("%(lhs)s >= (%(rhs)s || '-01-01')::date " return ("%(lhs)s >= (%(rhs)s || '-01-01')::date "
"AND %(lhs)s <= (%(rhs)s || '-12-31')::date" % "AND %(lhs)s <= (%(rhs)s || '-12-31')::date" %
{'lhs': lhs_sql, 'rhs': rhs_sql}, params) {'lhs': lhs_sql, 'rhs': rhs_sql}, params)
YearTransform.register_lookup(YearExact)
@YearTransform.register_lookup
class YearLte(models.lookups.LessThanOrEqual): class YearLte(models.lookups.LessThanOrEqual):
""" """
The purpose of this lookup is to efficiently compare the year of the field. The purpose of this lookup is to efficiently compare the year of the field.
@ -86,7 +87,6 @@ class YearLte(models.lookups.LessThanOrEqual):
# WHERE somecol <= '2013-12-31') # WHERE somecol <= '2013-12-31')
# but also make it work if the rhs_sql is field reference. # but also make it work if the rhs_sql is field reference.
return "%s <= (%s || '-12-31')::date" % (lhs_sql, rhs_sql), params return "%s <= (%s || '-12-31')::date" % (lhs_sql, rhs_sql), params
YearTransform.register_lookup(YearLte)
class SQLFunc(models.Lookup): class SQLFunc(models.Lookup):