Как проверить, совпадают ли два экземпляра модели Django в наборе атрибутов, и соответствующим образом аннотировать набор запросов? - PullRequest
1 голос
/ 04 июля 2019

В моем приложении есть модель "OptimizationResult", где я храню результаты математической оптимизации. Оптимизация распределяет временные интервалы по проектам. Мне нужно указать, отличаются ли текущие результаты от недавних результатов на основе набора атрибутов (в частности, не первичного ключа)

Атрибут optimisation_run является coutner для разных запусков. Проект является иностранным ключом к проекту.

Перезаписав функции __hash__ и __eq__ в модели, я могу сравнить различные экземпляры по

OptimizationResults.objects.filter(proj = 1).filter(optimization_run =1).first() == OptimizationResults.objects.filter(proj = 1).filter(optimization_run = 2).first()

. Но, насколько я понимаю, __eq__ и __hash__ недоступны в базе данных.

Как бы я соответственно прокомментировал результаты? Что-то вроде

OptimizationResults.objects.filter(optimization_run = 2).annotate(same_as_before = Case(When(),default=False))

Редактировать В код добавлен .first (), чтобы обеспечить наличие только одного элемента.

class OptimizationResult(models.Model):
    project = models.ForeignKey(project, on_delete=models.CASCADE)
    request_weight = models.IntegerField()
    periods_to_plan = models.IntegerField()
    unscheduled_periods = models.IntegerField()
    scheduled_periods = models.IntegerField()
    start = models.DateField(null=True, blank=True, default=None)
    end = models.DateField(null=True, blank=True, default=None)
    pub_date = models.DateTimeField('Erstellungsdatum', auto_now_add=True, editable=False)
    optimization_run= models.ForeignKey(OptimizationRun, on_delete=models.CASCADE)

Я бы хотел составить разные записи на основе start и end .

Редактировать 2

Моя бесплодная попытка с подзапросом:

old = OptimizationResult.objects.filter(project=OuterRef('pk')).filter(optimization_run=19)
newest = OptimizationResult.objects.filter(project=OuterRef('pk')).filter(optimization_run=21)
Project.objects.annotate(changed = Subquery(newest.values('start')[:1])== Subquery(old.values('start')[:1]))

приводит к тому, что TypeError: QuerySet.annotate () получил невыраженные выражения: False

1 Ответ

1 голос
/ 04 июля 2019

Мы можем использовать подзапрос здесь, чтобы сделать аннотацию:

from django.db.models import Exists, OuterRef, Subquery, Q

to_exclude = {'pk', 'id', 'project', 'project_id', 'optimization_run', 'optimization_run_id'}

subquery = OptimizationResult.objects.filter(
    project_id=OuterRef('project_id')
    optimization_run=1,
    **{f.name: OuterRef(f.name)
        for f in OptimizationResult._meta.get_fields()
        if f.name not in to_exclude
    }
)

OptimizationResult.objects.filter(
    optimization_run=2
).annotate(
    <b>are_same=Exist(subquery)</b>
)

Здесь мы будем таким образом аннотировать все OptimizationResult с optimization_run=2, с дополнительным атрибутом .are_same, который проверяет, существует ли объект OptimizationResult для optimization_run=1 и для того же project_id, где все поля одинаковы, кроме полей в наборе to_exclude.

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