summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/composite_pk/models/tenant.py1
-rw-r--r--tests/composite_pk/test_filter.py58
-rw-r--r--tests/composite_pk/tests.py9
-rw-r--r--tests/foreign_object/test_tuple_lookups.py18
-rw-r--r--tests/lookup/tests.py16
-rw-r--r--tests/queries/tests.py14
6 files changed, 83 insertions, 33 deletions
diff --git a/tests/composite_pk/models/tenant.py b/tests/composite_pk/models/tenant.py
index 6286ed2354..c85869afa7 100644
--- a/tests/composite_pk/models/tenant.py
+++ b/tests/composite_pk/models/tenant.py
@@ -44,6 +44,7 @@ class Comment(models.Model):
related_name="comments",
)
text = models.TextField(default="", blank=True)
+ integer = models.IntegerField(default=0)
class Post(models.Model):
diff --git a/tests/composite_pk/test_filter.py b/tests/composite_pk/test_filter.py
index fe942b9e5b..d4c6ef13e0 100644
--- a/tests/composite_pk/test_filter.py
+++ b/tests/composite_pk/test_filter.py
@@ -10,7 +10,7 @@ from django.db.models import (
)
from django.db.models.functions import Cast
from django.db.models.lookups import Exact
-from django.test import TestCase
+from django.test import TestCase, skipUnlessDBFeature
from .models import Comment, Tenant, User
@@ -182,6 +182,30 @@ class CompositePKFilterTests(TestCase):
Comment.objects.filter(pk__in=pks).order_by("pk"), objs
)
+ def test_filter_comments_by_pk_in_subquery(self):
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+ pk__in=Comment.objects.filter(pk=self.comment_1.pk),
+ ),
+ [self.comment_1],
+ )
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+ pk__in=Comment.objects.filter(pk=self.comment_1.pk).values(
+ "tenant_id", "id"
+ ),
+ ),
+ [self.comment_1],
+ )
+ self.comment_2.integer = self.comment_1.id
+ self.comment_2.save()
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+ pk__in=Comment.objects.values("tenant_id", "integer"),
+ ),
+ [self.comment_1],
+ )
+
def test_filter_comments_by_user_and_order_by_pk_asc(self):
self.assertSequenceEqual(
Comment.objects.filter(user=self.user_1).order_by("pk"),
@@ -440,16 +464,40 @@ class CompositePKFilterTests(TestCase):
queryset = Comment.objects.filter(**{f"id{lookup}": subquery})
self.assertEqual(queryset.count(), expected_count)
- def test_non_outer_ref_subquery(self):
- # If rhs is any non-OuterRef object with an as_sql() function.
+ def test_unsupported_rhs(self):
pk = Exact(F("tenant_id"), 1)
msg = (
- "'exact' subquery lookup of 'pk' only supports OuterRef objects "
- "(received 'Exact')"
+ "'exact' subquery lookup of 'pk' only supports OuterRef "
+ "and QuerySet objects (received 'Exact')"
)
with self.assertRaisesMessage(ValueError, msg):
Comment.objects.filter(pk=pk)
+ @skipUnlessDBFeature("allow_sliced_subqueries_with_in")
+ def test_filter_comments_by_pk_exact_subquery(self):
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+ pk=Comment.objects.filter(pk=self.comment_1.pk)[:1],
+ ),
+ [self.comment_1],
+ )
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+ pk__in=Comment.objects.filter(pk=self.comment_1.pk).values(
+ "tenant_id", "id"
+ )[:1],
+ ),
+ [self.comment_1],
+ )
+ self.comment_2.integer = self.comment_1.id
+ self.comment_2.save()
+ self.assertSequenceEqual(
+ Comment.objects.filter(
+ pk__in=Comment.objects.values("tenant_id", "integer"),
+ )[:1],
+ [self.comment_1],
+ )
+
def test_outer_ref_not_composite_pk(self):
subquery = Comment.objects.filter(pk=OuterRef("id")).values("id")
queryset = Comment.objects.filter(id=Subquery(subquery))
diff --git a/tests/composite_pk/tests.py b/tests/composite_pk/tests.py
index 6b09480fb0..18fa53d9c0 100644
--- a/tests/composite_pk/tests.py
+++ b/tests/composite_pk/tests.py
@@ -109,13 +109,10 @@ class CompositePKTests(TestCase):
def test_composite_pk_in_fields(self):
user_fields = {f.name for f in User._meta.get_fields()}
- self.assertEqual(user_fields, {"pk", "tenant", "id", "email", "comments"})
+ self.assertTrue({"pk", "tenant", "id"}.issubset(user_fields))
comment_fields = {f.name for f in Comment._meta.get_fields()}
- self.assertEqual(
- comment_fields,
- {"pk", "tenant", "id", "user_id", "user", "text"},
- )
+ self.assertTrue({"pk", "tenant", "id"}.issubset(comment_fields))
def test_pk_field(self):
pk = User._meta.get_field("pk")
@@ -174,7 +171,7 @@ class CompositePKTests(TestCase):
self.assertEqual(user.email, self.user.email)
def test_model_forms(self):
- fields = ["tenant", "id", "user_id", "text"]
+ fields = ["tenant", "id", "user_id", "text", "integer"]
self.assertEqual(list(CommentForm.base_fields), fields)
form = modelform_factory(Comment, fields="__all__")
diff --git a/tests/foreign_object/test_tuple_lookups.py b/tests/foreign_object/test_tuple_lookups.py
index 42717c4f11..008f118994 100644
--- a/tests/foreign_object/test_tuple_lookups.py
+++ b/tests/foreign_object/test_tuple_lookups.py
@@ -63,9 +63,11 @@ class TupleLookupsTests(TestCase):
)
def test_exact_subquery(self):
- with self.assertRaisesMessage(
- ValueError, "'exact' doesn't support multi-column subqueries."
- ):
+ msg = (
+ "The QuerySet value for the exact lookup must have 2 selected "
+ "fields (received 1)"
+ )
+ with self.assertRaisesMessage(ValueError, msg):
subquery = Customer.objects.filter(id=self.customer_1.id)[:1]
self.assertSequenceEqual(
Contact.objects.filter(customer=subquery).order_by("id"), ()
@@ -140,11 +142,11 @@ class TupleLookupsTests(TestCase):
def test_tuple_in_subquery_must_have_2_fields(self):
lhs = (F("customer_code"), F("company_code"))
rhs = Customer.objects.values_list("customer_id").query
- with self.assertRaisesMessage(
- ValueError,
- "'in' subquery lookup of ('customer_code', 'company_code') "
- "must have 2 fields (received 1)",
- ):
+ msg = (
+ "The QuerySet value for the 'in' lookup must have 2 selected "
+ "fields (received 1)"
+ )
+ with self.assertRaisesMessage(ValueError, msg):
TupleIn(lhs, rhs)
def test_tuple_in_subquery(self):
diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py
index df96546d04..e19fbca521 100644
--- a/tests/lookup/tests.py
+++ b/tests/lookup/tests.py
@@ -789,6 +789,14 @@ class LookupTests(TestCase):
sql = ctx.captured_queries[0]["sql"]
self.assertIn("IN (%s)" % self.a1.pk, sql)
+ def test_in_select_mismatch(self):
+ msg = (
+ "The QuerySet value for the 'in' lookup must have 1 "
+ "selected fields (received 2)"
+ )
+ with self.assertRaisesMessage(ValueError, msg):
+ Article.objects.filter(id__in=Article.objects.values("id", "headline"))
+
def test_error_messages(self):
# Programming errors are pointed out with nice error messages
with self.assertRaisesMessage(
@@ -1364,6 +1372,14 @@ class LookupTests(TestCase):
authors = Author.objects.filter(id=authors_max_ids[:1])
self.assertEqual(authors.get(), newest_author)
+ def test_exact_query_rhs_with_selected_columns_mismatch(self):
+ msg = (
+ "The QuerySet value for the exact lookup must have 1 "
+ "selected fields (received 2)"
+ )
+ with self.assertRaisesMessage(ValueError, msg):
+ Author.objects.filter(id=Author.objects.values("id", "name")[:1])
+
def test_isnull_non_boolean_value(self):
msg = "The QuerySet value for an isnull lookup must be True or False."
tests = [
diff --git a/tests/queries/tests.py b/tests/queries/tests.py
index 45866fd50f..c429a93af3 100644
--- a/tests/queries/tests.py
+++ b/tests/queries/tests.py
@@ -922,20 +922,6 @@ class Queries1Tests(TestCase):
[self.t2, self.t3],
)
- # Multi-valued values() and values_list() querysets should raise errors.
- with self.assertRaisesMessage(
- TypeError, "Cannot use multi-field values as a filter value."
- ):
- Tag.objects.filter(
- name__in=Tag.objects.filter(parent=self.t1).values("name", "id")
- )
- with self.assertRaisesMessage(
- TypeError, "Cannot use multi-field values as a filter value."
- ):
- Tag.objects.filter(
- name__in=Tag.objects.filter(parent=self.t1).values_list("name", "id")
- )
-
def test_ticket9985(self):
# qs.values_list(...).values(...) combinations should work.
self.assertSequenceEqual(