#37171: Query that worked in Django 5.x now throws error: "The QuerySet value
for
an exact lookup must be limited to one result using slicing"
-------------------------------------+-------------------------------------
Reporter: Mark Baird | Type: Bug
Status: new | Component: Database
| layer (models, ORM)
Version: 6.0 | Severity: Normal
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
We have a query that worked fine in Django 5.x but during our Django 6
upgrade we ran into failing tests because the query now throws an error.
We were attempting to upgrade from Django 5.2.15 to Django 6.0.6. I've
read through the change logs and I'm not seeing anything that seems to
indicate that this is an expected change in Django 6.
I've attempted to create a minimal code example to demonstrate the issue.
Given the following models:
{{{
class Bill(models.Model):
amount = models.DecimalField(max_digits=17, decimal_places=2,
blank=True, default=0)
class PaymentRequest(models.Model):
bill = models.ForeignKey(Bill, on_delete=models.CASCADE,
related_name="payment_requests")
date_sent = models.DateField(blank=True, null=True)
class PartialPayment(models.Model):
payment_request = models.ForeignKey(PaymentRequest,
on_delete=models.CASCADE, related_name="partial_payments")
amount = models.DecimalField(max_digits=17, decimal_places=2,
blank=True, default=0)
date_received = models.DateField(blank=True, null=True)
}}}
This test throws an exception in Django 6, while it worked fine in Django
5:
{{{
class BillPaymentsTests(TestCase):
def test_query_unpaid_bills(self):
bill = models.Bill(amount=100.00)
payment_request = models.PaymentRequest(bill=bill)
models.PartialPayment(payment_request=payment_request,
amount=50.00)
models.PartialPayment(payment_request=payment_request,
amount=50.00)
subquery = (models.PaymentRequest.objects
.filter(bill=OuterRef("pk")).values("bill")
.annotate(total_paid=Sum("partial_payments__amount"))
.values("total_paid"))
unpaid_bills =
models.Bill.objects.annotate(total_paid=Subquery(subquery)).exclude(amount=F("total_paid"))
self.assertNotIn(bill, unpaid_bills)
}}}
The exception thrown is:
{{{
ValueError: The QuerySet value for an exact lookup must be limited to one
result using slicing.
}}}
On the line:
{{{
unpaid_bills =
models.Bill.objects.annotate(total_paid=Subquery(subquery)).exclude(amount=F("total_paid"))
}}}
I recognize that I could simplify this code to remove the subquery, but
please understand this is just a minimal example to demonstrate what
appears to be a regression bug in Django 6. The actual code in my
application is much more complicated and the subquery is needed.
----
I did discover a work-around, by simply swapping the fields in the
exclude() condition, like so:
{{{
unpaid_bills =
models.Bill.objects.annotate(total_paid=Subquery(subquery)).exclude(total_paid=F("amount"))
}}}
So we were able to get past this issue and complete our Django 6 upgrade,
but I wanted to log this bug so the Django team is aware of the issue.
--
Ticket URL: <https://code.djangoproject.com/ticket/37171>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/0107019ecc5b7f4f-492bbfdc-360f-4cfd-a23a-9505ea4fe81b-000000%40eu-central-1.amazonses.com.