2

in Django's doc is the following code snippet

from django.db import models
from django.utils import timezone
import datetime


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

Pycharm highlights self.pub_date and shouts

Expected type 'timedelta', got 'DateTimeField' instead

How do I get rid of this and do things right?

Gulzar
  • 23,452
  • 27
  • 113
  • 201
  • 1
    This is likely a bug with PyCharm's (great but not perfect) linting. You can report it to JetBrains if you want. Also, if you add `# noqa` to the end of the line, PyCharm will not display warnings. – jfaccioni Apr 27 '20 at 20:55
  • @jfaccioni nice fact to know, thanks :) however, it doesn't make it disappear... – Gulzar Apr 27 '20 at 20:59
  • I believe the `# noqa` comment works only in the latest version of PyCharm. To remove the warning in earlier versions, refer to [this answer](https://stackoverflow.com/questions/61279148/pycharm-says-readline-import-not-being-used/61279360#61279360). – jfaccioni Apr 27 '20 at 21:02

2 Answers2

5

While the code is functional, it suffers from a typing issue which PyCharm is highlighting. A ticket was raised to Django to correct the documentation but was closed without implementing.

The solution is also in the Django ticket, copied here for completeness.

return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

becomes

return self.pub_date >= (timezone.now() - datetime.timedelta(days=1)).timestamp()
Nils Lindemann
  • 1,146
  • 1
  • 16
  • 26
Steven B.
  • 284
  • 4
  • 10
2

When using the Steven B.'s solution, it throws a TypeError exception ('>=' not supported between instances of 'datetime.datetime' and 'float').

from django.db import models
from django.utils import timezone
import datetime


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        return self.pub_date >= (datetime.datetime.now() - datetime.timedelta(days=1)).timestamp()

So when comparing datetimes in Django, we have to keep in mind that the datetime object is naive in Python by default, so you need to make both of them either naive or aware datetime objects. All credit to Viren Rajput in this answer

Because of that, the following solution works correctly:

from django.db import models
from django.utils import timezone
import datetime
import pytz


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        return self.pub_date >= (timezone.now() - datetime.timedelta(days=1)).replace(tzinfo=pytz.UTC)

Note: If we cast both expressions to float using the timestamp() method:

from django.db import models
import datetime


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        return self.pub_date.timestamp() >= (datetime.datetime.now() - datetime.timedelta(days=1)).timestamp()

(It could work, but PyCharm would point out the warning Unresolved attribute reference 'timestamp' for class 'DateTimeField')

Django version: 3.2.5

Rafael VC
  • 406
  • 5
  • 12