Фильтровать объект модели по разнице в днях - PullRequest
0 голосов
/ 19 июня 2020

В моей модели есть поле даты, и я хочу отфильтровать модель по последним 7 дням.

class Count(models.Model):
    task = models.ForeignKey(Task, related_name = 'counts', on_delete = models.CASCADE)
    start_time = models.DateTimeField(null = True, blank = True)
    end_time = models.DateTimeField(null = True, blank = True)
    time_spent = models.PositiveIntegerField()
    deleted = models.BooleanField(default = False)

    class Meta():
        ordering = ['accesses']

    def __str__(self):
        return f'{self.task.department} - {self.accesses.first().user} [{self.time_spent} min]'

    def stamped_date(self):
        if not self.start_time:
            return self.accesses.first().date
        return self.start_time

    def users(self):
        return list(set(map(lambda x: x.user, list(self.accesses.all()))))

Мне нужно отфильтровать каждый счетчик, который имеет "stamped_date" за последние 7 дней.

То, что я пытался сделать (в модели):

    def daysBy(self):
        return (datetime.now() - self.stamped_date()).days

для фильтрации следующим образом:

Count.objects.filter(daysBy__let = 7)

Однако datetime.now () требует объект часового пояса, в противном случае будет выдана следующая ошибка:

TypeError: can't subtract offset-naive and offset-aware datetimes

Я также чувствую, что это может быть не самый правильный способ достижения моей цели, пожалуйста, исправьте меня лучшим способом.

Или. . дать мне способ вставить объект часового пояса, связанный с настройкой TIME_ZONE.

Ответы [ 3 ]

2 голосов
/ 19 июня 2020

Вы хотите отфильтровать набор запросов и получить счетчик, если штампованная_дата находится в пределах семи дней

Вы будете справедливы, если это стандартное требование для создания менеджера моделей для обработки этого

К чему вы стремитесь. Потому что, сделав это, вы можете вызвать count () в возвращенном наборе запросов.

import datetime

    Count.objects.get_stamped_date().count()

Менеджер модели будет выглядеть так:

    class CountManager(models.Manager):

        def get_stamped_date(self):
            todays_date = timezone.now()
            seven_days_ago = datetime.timedelta(days=7)
            qs = super().get_queryset()
            count = qs.filter(start_time__range=[seven_days_ago, todays_date])

        return count

Затем обновите свою модель, чтобы включить диспетчер

Count(models.Models):
    objects = CountManager()

Честно говоря, ваш stamped_date должен быть атрибутом поля, который должен работать с вашим методом save () вашей модели, так что это немного сбивает с толку, почему вы сделали это именно так. При использовании метода сохранения (стандартного) позвольте экземпляру модели проверять каждый раз, когда нет времени начала, и сохраните ваше поле self.access datetime, которое я не вижу здесь ссылки на поле stamped_date

Также только для вишенка на вершине, возможно, было бы даже лучше позволить аргументу менеджеру модели сказать, сколько дней, чтобы его не фиксировали на семи днях.

2 голосов
/ 19 июня 2020

из Часовые пояса - Django Документация :

Когда включена поддержка часового пояса (USE_TZ = True), Django использует объекты datetime с учетом часового пояса . Если ваш код создает объекты datetime, они тоже должны это знать. В этом режиме приведенный выше пример выглядит следующим образом:

   from django.utils import timezone

   now = timezone.now()

Надеюсь, это поможет.

1 голос
/ 19 июня 2020

Вы можете выполнить этот запрос с помощью оператора диапазона, подобного этому.

oldDate = datetime.now() - datetime.timedelta(days =7)
Count.objects.filter(start_time__range=(oldDate, datetime.now()))

EDIT: для выполнения такого рода запросов с помощью метода фильтрации созданное вами значение должно быть полем модели. Вы можете добиться этого, переопределив метод сохранения следующим образом:

# Create the stamped date model field
stamped_date = models.DateTimeField(null=True)

#override the save method for your custom saving logic
def save(self, *args, **kwargs):
        if not self.start_time:
            self.stamped_date = self.accesses.first().date
        else:
            self.stamped_date = self.start_time
        super().save(*args, **kwargs)  # Call the "real" save() method.

Django docs

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...