Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion tests/aggregation_regress/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -636,10 +636,11 @@ def test_field_error(self):
Max("foo")
)

def test_more(self):
def test_count_after_count_function(self):
# Old-style count aggregations can be mixed with new-style
self.assertEqual(Book.objects.annotate(num_authors=Count("authors")).count(), 6)

def test_aggregates_over_annotations(self):
# Non-ordinal, non-computed Aggregates over annotations correctly
# inherit the annotation's internal type if the annotation is ordinal
# or computed
Expand All @@ -653,10 +654,12 @@ def test_more(self):
)
self.assertEqual(vals, {"avg_price__max": 75.0})

def test_aliases_quoted(self):
# Aliases are quoted to protected aliases that might be reserved names
vals = Book.objects.aggregate(number=Max("pages"), select=Max("pages"))
self.assertEqual(vals, {"number": 1132, "select": 1132})

def test_select_related(self):
# Regression for #10064: select_related() plays nice with aggregates
obj = (
Book.objects.select_related("publisher")
Expand All @@ -680,6 +683,7 @@ def test_more(self):
},
)

def test_exclude_on_aggregate(self):
# Regression for #10010: exclude on an aggregate field is correctly
# negated
self.assertEqual(len(Book.objects.annotate(num_authors=Count("authors"))), 6)
Expand Down
40 changes: 35 additions & 5 deletions tests/lookup/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ def test_in_bulk_values_list_flat_field_id(self):
},
)

def test_values(self):
def test_values_filter_and_no_fields(self):
# values() returns a list of dictionaries instead of object instances,
# and you can specify which fields you want to retrieve.
self.assertSequenceEqual(
Expand All @@ -592,6 +592,8 @@ def test_values(self):
},
],
)

def test_values_single_field(self):
self.assertSequenceEqual(
Article.objects.values("headline"),
[
Expand All @@ -604,10 +606,14 @@ def test_values(self):
{"headline": "Article 1"},
],
)

def test_values_filter_and_single_field(self):
self.assertSequenceEqual(
Article.objects.filter(pub_date__exact=datetime(2005, 7, 27)).values("id"),
[{"id": self.a2.id}, {"id": self.a3.id}, {"id": self.a7.id}],
)

def test_values_two_fields(self):
self.assertSequenceEqual(
Article.objects.values("id", "headline"),
[
Expand All @@ -620,6 +626,8 @@ def test_values(self):
{"id": self.a1.id, "headline": "Article 1"},
],
)

def test_values_iterator(self):
# You can use values() with iterator() for memory savings,
# because iterator() uses database-level iteration.
self.assertSequenceEqual(
Expand All @@ -634,6 +642,8 @@ def test_values(self):
{"headline": "Article 1", "id": self.a1.id},
],
)

def test_values_extra(self):
# The values() method works with "extra" fields specified in
# extra(select).
self.assertSequenceEqual(
Expand Down Expand Up @@ -675,6 +685,8 @@ def test_values(self):
}
],
)

def test_values_relations(self):
# You can specify fields from forward and reverse relations, just like
# filter().
self.assertSequenceEqual(
Expand Down Expand Up @@ -757,6 +769,8 @@ def test_values(self):
},
],
)

def test_values_nonexistent_field(self):
# However, an exception FieldDoesNotExist will be thrown if you specify
# a nonexistent field name in values() (a field that is neither in the
# model nor in extra(select)).
Expand All @@ -768,6 +782,8 @@ def test_values(self):
Article.objects.extra(select={"id_plus_one": "id + 1"}).values(
"id", "id_plus_two"
)

def test_values_no_field_names(self):
# If you don't specify field names to values(), all are returned.
self.assertSequenceEqual(
Article.objects.filter(id=self.a5.id).values(),
Expand All @@ -782,7 +798,7 @@ def test_values(self):
],
)

def test_values_list(self):
def test_values_list_filter_and_no_fields(self):
# values_list() is similar to values(), except that the results are
# returned as a list of tuples, rather than a list of dictionaries.
# Within each tuple, the order of the elements is the same as the order
Expand All @@ -806,8 +822,9 @@ def test_values_list(self):
),
],
)
# RemovedInDjango70Warning: When the deprecation ends, remove this
# assertion.

# RemovedInDjango70Warning: When the deprecation ends, remove this test.
def test_values_list_flat_no_fields(self):
with ignore_warnings(category=RemovedInDjango70Warning):
qs = Article.objects.values_list(flat=True)
self.assertSequenceEqual(
Expand All @@ -822,6 +839,8 @@ def test_values_list(self):
self.a1.id,
],
)

def test_values_list_single_field(self):
self.assertSequenceEqual(
Article.objects.values_list("headline"),
[
Expand All @@ -834,6 +853,8 @@ def test_values_list(self):
("Article 1",),
],
)

def test_values_list_single_field_order_by(self):
self.assertSequenceEqual(
Article.objects.values_list("id").order_by("id"),
[
Expand All @@ -846,6 +867,8 @@ def test_values_list(self):
(self.a7.id,),
],
)

def test_values_list_flat_order_by(self):
self.assertSequenceEqual(
Article.objects.values_list("id", flat=True).order_by("id"),
[
Expand All @@ -858,6 +881,8 @@ def test_values_list(self):
self.a7.id,
],
)

def test_values_list_extra(self):
self.assertSequenceEqual(
Article.objects.extra(select={"id_plus_one": "id+1"})
.order_by("id")
Expand Down Expand Up @@ -900,6 +925,8 @@ def test_values_list(self):
(self.a7.id, self.a7.id + 1),
],
)

def test_values_list_relations(self):
args = ("name", "article__headline", "article__tag__name")
self.assertSequenceEqual(
Author.objects.values_list(*args).order_by(*args),
Expand All @@ -915,7 +942,10 @@ def test_values_list(self):
(self.au2.name, self.a7.headline, self.t3.name),
],
)
with self.assertRaises(TypeError):

def test_values_list_flat_more_than_one_field(self):
msg = "'flat' is not valid when values_list is called with more than one field."
with self.assertRaisesMessage(TypeError, msg):
Article.objects.values_list("id", "headline", flat=True)

# RemovedInDjango70Warning: When the deprecation ends, replace with:
Expand Down
66 changes: 39 additions & 27 deletions tests/many_to_one/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,33 +278,6 @@ def test_selects(self):
),
[new_article1, self.a],
)
# The underlying query only makes one join when a related table is
# referenced twice.
queryset = Article.objects.filter(
reporter__first_name__exact="John", reporter__last_name__exact="Smith"
)
self.assertNumQueries(1, list, queryset)
self.assertEqual(
queryset.query.get_compiler(queryset.db).as_sql()[0].count("INNER JOIN"), 1
)

# The automatically joined table has a predictable name.
self.assertSequenceEqual(
Article.objects.filter(reporter__first_name__exact="John").extra(
where=["many_to_one_reporter.last_name='Smith'"]
),
[new_article1, self.a],
)
# ... and should work fine with the string that comes out of
# forms.Form.cleaned_data.
self.assertQuerySetEqual(
(
Article.objects.filter(reporter__first_name__exact="John").extra(
where=["many_to_one_reporter.last_name='%s'" % "Smith"]
)
),
[new_article1, self.a],
)
# Find all Articles for a Reporter.
# Use direct ID check, pk check, and object comparison
self.assertSequenceEqual(
Expand Down Expand Up @@ -343,6 +316,45 @@ def test_selects(self):
[new_article1, self.a],
)

def test_joined_sql(self):
# The underlying query only makes one join when a related table is
# referenced twice.
queryset = Article.objects.filter(
reporter__first_name__exact="John", reporter__last_name__exact="Smith"
)
self.assertNumQueries(1, list, queryset)
self.assertEqual(
queryset.query.get_compiler(queryset.db).as_sql()[0].count("INNER JOIN"), 1
)

def test_joined_extra(self):
new_article1 = self.r.article_set.create(
headline="John's second story",
pub_date=datetime.date(2005, 7, 29),
)
self.r2.article_set.create(
headline="Paul's story",
pub_date=datetime.date(2006, 1, 17),
)
# The automatically joined table has a predictable name.
self.assertSequenceEqual(
Article.objects.filter(reporter__first_name__exact="John").extra(
where=["many_to_one_reporter.last_name='Smith'"]
),
[new_article1, self.a],
)
# ... and should work fine with the string that comes out of
# forms.Form.cleaned_data.
self.assertQuerySetEqual(
(
Article.objects.filter(reporter__first_name__exact="John").extra(
where=["many_to_one_reporter.last_name=%s"],
params=["Smith"],
)
),
[new_article1, self.a],
)

def test_reverse_selects(self):
a3 = Article.objects.create(
headline="Third article",
Expand Down
1 change: 1 addition & 0 deletions tests/queries/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1860,6 +1860,7 @@ def test_ordering(self):
[self.rank1, self.rank2, self.rank3],
)

def test_ordering_with_extra(self):
# Ordering of extra() pieces is possible, too and you can mix extra
# fields and model fields in the ordering.
self.assertSequenceEqual(
Expand Down
Loading