Fixed #26056 -- Added QuerySet.values()/values_list() support for ArrayField's __overlap lookup.

Thanks Mads Jensen and kosz85 and the initial patch.
This commit is contained in:
Ben Cail 2022-10-26 09:58:08 -04:00 committed by Mariusz Felisiak
parent 81b1c167bf
commit fbde929b19
4 changed files with 35 additions and 1 deletions

View File

@ -1,5 +1,6 @@
from django.db.models import Transform
from django.db.models.lookups import PostgresOperatorLookup
from django.db.models.sql.query import Query
from .search import SearchVector, SearchVectorExact, SearchVectorField
@ -18,6 +19,13 @@ class Overlap(PostgresOperatorLookup):
lookup_name = "overlap"
postgres_operator = "&&"
def get_prep_lookup(self):
from .expressions import ArraySubquery
if isinstance(self.rhs, Query):
self.rhs = ArraySubquery(self.rhs)
return super().get_prep_lookup()
class HasKey(PostgresOperatorLookup):
lookup_name = "has_key"

View File

@ -170,7 +170,7 @@ Returns objects where the data shares any results with the values passed. Uses
the SQL operator ``&&``. For example::
>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.create(name='Second post', tags=['thoughts', 'tutorial'])
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
>>> Post.objects.filter(tags__overlap=['thoughts'])
@ -179,6 +179,14 @@ the SQL operator ``&&``. For example::
>>> Post.objects.filter(tags__overlap=['thoughts', 'tutorial'])
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
>>> Post.objects.filter(tags__overlap=Post.objects.values_list('tags'))
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
.. versionchanged:: 4.2
Support for ``QuerySet.values()`` and ``values_list()`` as a right-hand
side was added.
.. fieldlookup:: arrayfield.len
``len``

View File

@ -102,6 +102,9 @@ Minor features
<django.contrib.postgres.search.TrigramStrictWordDistance>` expressions allow
using trigram strict word similarity.
* The :lookup:`arrayfield.overlap` lookup now supports ``QuerySet.values()``
and ``values_list()`` as a right-hand side.
:mod:`django.contrib.redirects`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -414,6 +414,21 @@ class TestQuerying(PostgreSQLTestCase):
[obj_1, obj_2],
)
def test_overlap_values(self):
qs = NullableIntegerArrayModel.objects.filter(order__lt=3)
self.assertCountEqual(
NullableIntegerArrayModel.objects.filter(
field__overlap=qs.values_list("field"),
),
self.objs[:3],
)
self.assertCountEqual(
NullableIntegerArrayModel.objects.filter(
field__overlap=qs.values("field"),
),
self.objs[:3],
)
def test_lookups_autofield_array(self):
qs = (
NullableIntegerArrayModel.objects.filter(