Как создать фильтр набора запросов Django, сравнивающий два поля даты в одной модели

82

Попытка получить запрос, в котором запись Activity устарела в моем индексе Solr. Я хочу проверить, больше ли Activity.updatedдата в базе данных, чем Activity.added_toSolr_dateдля той же записи.

stale_activities_queryset = Activity.objects.filter(updated__gte = self.added_toSolr_date) 

Модель

class Activity(models.Model):
    # Last time entry / metric was updated in the Activity model database
    updated =  models.DateTimeField( verbose_name="CRUD date")
    # When it was added to Solr Index Date
    added_toSolr_date = models.DateTimeField(blank=True, null=True, verbose_name="Added to Solr Index Date")

Я сослался на документы Django Query: https://docs.djangoproject.com/en/1.4/ref/models/querysets/ И модульные тесты для образцов: https://github.com/django/django/blob/master/tests/ modeltests / или_lookups / tests.py

Также искал здесь, в Stackoverflow. Во всех примерах используется введенная дата вместо сравнения двух полей даты в одной модели.

Карлос Феррейра
источник

Ответы:

162

F объекты.

from django.db.models import F
stale_activities = Activity.objects.filter(updated__gte=F('added_toSolr_date')) 
Юдзи Томита Томита
источник
Спасибо! Как вы это узнали?
Карлос Феррейра,
6
@CarlosFerreira, за годы использования django каждый день. Я не могу сказать когда.
Yuji 'Tomita' Tomita
хорошее решение! почти опубликовал тот же вопрос
Рон
Благодаря! Я это искал!
Alex Santos
2
Кажется, что это не удается, если одна из дат равна NULL. Использование Q для проверки нуля или сравнения и все равно не удается. Даже если бы этого не было в MySQL, кто-нибудь еще это видел?
Пол Кенджора
3

Решение Yuji Tomita, к сожалению, не сработало.

Рассмотрим модель ниже:

class list(models.Model):
    text = models.CharField(max_length=140)
    created = models.DateTimeField()
    modified = models.DateTimeField()

Набор запросов:

my_list = todolist.objects.order_by('created').filter(created__gte=F('modified'))

Шаблон:

{% if my_list %}
{% for list in my_list %}
{{ list.text}}
{% endfor %}
{% else %}
<p>there is no list</p>
{% endif %}

В итоге я получаю пустой список, но знаю, что это неверно. Я также использовал в шаблоне следующее (без фильтра набора запросов):

{% if list.created|date:'d m y h:i:s' == list.modified|date:'d m y h:i:s' %}

Это сработало, но я бы предпочел более элегантное решение.

Сергей Кривой
источник
При быстром чтении кажется, что вы делаете две разные вещи в своем фильтре набора запросов и в нашем коде шаблона. В первом случае вы используете «gte», а во втором - «==». Не поэтому ли они дают одинаковые результаты? Я сам пытаюсь понять, почему использование mydate__exact = F('my_other_date')в запросе не работает, когда my_other_date равно None.
jenniwren,
У меня была еще одна причина, по которой это не сработало. Используя django-extensions TimeStampedModel, то createdи updatedвременные метки равны вплоть до milisecond. Есть минимальная задержка. Мое быстрое решение заключалось в том, чтобы просто сравнить его со вторым.
tschale