Hello Ricardo,
This could be a regression caused by a patch addressing a regression in 3.0.3[0].
Did you also notice this behaviour on Django 2.2.x or was this project started from Django 3.0?
From what I can see though I find it strange that the ExpressionWrapper of end_total_time
have an output_field of BigIntegerField instead of DurationField. That could be the origin
of your issue.
Cheers,
Simon
[0] https://github.com/django/django/commit/02cda09b13e677db01863fa0a7112dba631b9c5c
Le mercredi 19 février 2020 13:08:57 UTC-5, Ricardo H a écrit :
Hello, after I updated django from 3.0.2 to 3.0.3 the result of the following code has changed when using a MySQL database. It produces a wrong sql query and also the wrong result for "end_total_time" attribute.Is this a bug ? also is there any other way to get the wright result using 3.0.3 ?Thank you.
models.pyfrom datetime import datetime
import pytz
from django.db import models
from django.db.models.functions import Cast
class PhaseQueryset(models.QuerySet):
def with_duration(self,):
base_date = datetime(2000, 1, 3, 0, tzinfo=pytz.utc)
# When I use base_date to do the end_total_time math in 3.0.3 together
# with ended_at annotated, it creates a wrong query
qs = self.annotate(
ended_at=models.Case(
models.When(
models.Q(type='TYPEONE'),
then=models.functions.Now()
),
default=models.F('started_at'),
output_field=models.DateTimeField (),
),
base_date=models.functions.Cast (
models.Value(base_date),
output_field=models.DateTimeField ()
),
end_total_time=models.ExpressionWrapper (
models.F('ended_at') - models.F('base_date'),
output_field=models.fields.BigIntegerField ()
)
)
return qs
# Create your models here.
class Phase(models.Model):
objects = PhaseQueryset().as_manager()
started_at = models.DateTimeField()
type = models.CharField(max_length=40) tests.pyfrom datetime import datetime, timedelta
import pytz
from django.test import TestCase
from daterror.models import Phase
# Create your tests here.
class TestDateProblem(TestCase):
def setUp(self,):
past = datetime.now(tz=pytz.UTC) - timedelta(days=30)
Phase.objects.create(started_at =past, type='TYPEONE')
past = datetime.now(tz=pytz.UTC) - timedelta(days=33)
Phase.objects.create(started_at =past, type='TYPETWO')
past = datetime.now(tz=pytz.UTC) - timedelta(days=34)
Phase.objects.create(started_at =past, type='TYPETHREE')
def test_timedifference_not_none(self ,):
phases = Phase.objects.all().with_duration ()
print(phases[0].end_total_time)
print(phases[1].end_total_time)
print(phases[2].end_total_time)
self.assertNotEqual(None, phases[0].end_total_time)
self.assertNotEqual(None, phases[1].end_total_time)
self.assertNotEqual(None, phases[2].end_total_time)
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/4542b03e-797a-4e06-99c2-5ca77ccd4aec%40googlegroups.com.
No comments:
Post a Comment