Browse Source

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

Marc Tamlyn 10 years ago
parent
commit
92a17eaae0

+ 4 - 12
django/contrib/postgres/fields/array.py

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

+ 1 - 0
django/db/models/lookups.py

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

+ 12 - 0
docs/howto/custom-lookups.txt

@@ -46,6 +46,18 @@ it with ``Field`` directly::
   from django.db.models.fields import Field
   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
 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

+ 3 - 0
docs/releases/1.8.txt

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

+ 2 - 2
tests/custom_lookups/tests.py

@@ -50,6 +50,7 @@ class YearTransform(models.Transform):
         return models.IntegerField()
 
 
+@YearTransform.register_lookup
 class YearExact(models.lookups.Lookup):
     lookup_name = 'exact'
 
@@ -66,9 +67,9 @@ class YearExact(models.lookups.Lookup):
         return ("%(lhs)s >= (%(rhs)s || '-01-01')::date "
                 "AND %(lhs)s <= (%(rhs)s || '-12-31')::date" %
                 {'lhs': lhs_sql, 'rhs': rhs_sql}, params)
-YearTransform.register_lookup(YearExact)
 
 
+@YearTransform.register_lookup
 class YearLte(models.lookups.LessThanOrEqual):
     """
     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')
         # but also make it work if the rhs_sql is field reference.
         return "%s <= (%s || '-12-31')::date" % (lhs_sql, rhs_sql), params
-YearTransform.register_lookup(YearLte)
 
 
 class SQLFunc(models.Lookup):