djangodjango-modelsdjango-ormdjango-mysql

Django Annotate ExpressionWrapper Does not Return Expected Type


I have the following models:

class Creditor(models.Model):
    terms_of_payment = models.IntegerField(
        blank=False,
        null=False
    )

class Invoice(models.Model):
    creditor = models.ForeignKey(
        Creditor,
        blank=False,
        null=False,
        on_delete=models.CASCADE
    )
    reception_date = models.DateField(
        blank=True,
        null=True
    )

I am getting type int for due_on from the following queryset, instead of datetime.date and can't figure out why.

invoices = Invoice.objects.annotate(
    due_on=ExpressionWrapper(
        F('reception_date') + F('creditor__terms_of_payment'),
        output_field=DateField()
    )
)

The database I'm using is MySQL. So basically if reception_date=datetime.date(2021, 5, 13) and terms_of_payment=2, I expect to get datetime.date(2021, 5, 15) but I'm getting 2021515 which is <class 'int'>.


Solution

  • I finally found the solution. The problem was terms_of_payment was an IntegerField instead of DurationField. In order for this queryset to yield a datetime, always a DurationField should be added to a DateTimeField. These corresponds to datetime.datetime and datetime.timedela in Python.

    class Creditor(models.Model):
    
        terms_of_payment = models.DurationField(
            default=datetime.timedelta(days=30)
        )