Django ORM Получение пользователей, которые НЕ обновляли информацию о своей зарплате за последний 1 год (Simlpe History )

Я хочу вывести пользователей, которые не обновляли информацию о своей зарплате за последний 1 год. НО С помощью ORM, а не For Loop.

from simple_history.models import HistoricalRecords



class User(AbstractUser):
    ...
    salary_expectation = models.IntegerField()
    history = HistoricalRecords(cascade_delete_history=True)
    

################################################################

    User.objects.filter(# MAGIC )  # Get users who have NOT updated their salary information in the last year

Я вижу, что это пакет, который имеет свою документацию по запросу его записей, см. ниже: https://django-simple-history.readthedocs.io/en/latest/querying_history.html

тем не менее, вы можете сделать это интуитивно, следуя обычному поведению Django и нескольким знаниям SQL, я бы ожидал, что таблица поля history скорее всего имеет отношения один-ко-многим с таблицей users, поэтому я бы сделал следующее: сначала открыл базу данных, нашел столбец, который показывает дату изменения, записал его имя и затем написал этот ORM запрос ниже

sub_query =  ~Q(history__date_column_name__lte= "Replace with end of date", history__date_column_name__gte= "Replace with beginning of date", affected_column_name="salary_expectation")

users = User.objects.filter(sub_query)

не забудьте импортировать Q

from django.db.models import Q

Вам не нужно проверять HistoricalRecords класс на наличие этой информации.

  1. Добавьте поля created_at и updated_at (date_time_fields) в вашу User модель
class User(...):
    ...
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
  1. Код квариры
from django.db.models.functions import Now, ExtractDay
from django.contrib.auth import get_user_model

User = get_user_model()

users = User.objects.annotate(
                # Calculate duration between now and last update date saved
                duration=models.ExpressionWrapper(
                    Now() - models.F("updated_at"),
                    output_field=models.DurationField()
                ),

                # Extract the amount of days in the duration
                days=ExtractDay('duration'),

                # Check if the number of days between the 2 fields exceeds 1 year (365.25 Days)
                last_update_beyond_a_year=models.Case(
                    models.When(
                        models.Q(days__gte=365.25),
                        then=True
                    ),
                    default=False,
                    output_field=models.BooleanField()
                )
            # Then filter 
            ).filter(last_update_beyond_a_year=True)

и Вуаля!

Вернуться на верх