Добавлять увеличивающееся целое число в набор запросов при каждом касании объекта в Django - PullRequest
0 голосов
/ 18 февраля 2019

Я пытаюсь добавить возрастающее целое число, в этом случае уникальный порядковый номер в диапазоне от [1, n], где n - количество последовательностей в заданном расписании.

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

Sequence.objects.filter(schedule=schedule).order_by('start', 'id')

и присвоения возрастающего номера каждой последовательности.Кроме того, где было бы идеальным местом для реализации этого метода, если бы я хотел, чтобы он выполнялся каждый раз, когда новая последовательность создается, удаляется или последовательность обновляет поле start.Я думал о методе save() и delete(), однако я не хочу обновлять, когда обновляются только другие поля в последовательности.

Это моя модель последовательности

class Sequence(models.Model):

    number = models.PositiveIntegerField(
        verbose_name='sequence number',
        help_text='auto incrementing sequence number',
    )
    schedule = models.ForeignKey(
        to=Schedule,
        verbose_name='schedule',
        on_delete=models.CASCADE,
        related_name='sequences',
        help_text='schedule primary key',
    )
    start = models.DateTimeField(
        verbose_name='start date',
        help_text='sequence starting datetime',
    )
    end = models.DateTimeField(
        verbose_name='end date',
        help_text='sequence ending datetime',
    )

1 Ответ

0 голосов
/ 18 февраля 2019

Ну, вы могли бы (не говоря «должен») использовать для этого сигналы Джанго .

В Django есть «диспетчер сигналов», который помогает получать отсоединенные приложения для полученияуведомление, когда действия происходят в другом месте в рамках.Короче говоря, сигналы позволяют определенным отправителям уведомлять группу получателей о том, что какое-то действие имело место. Они особенно полезны, когда многие фрагменты кода могут интересоваться одними и теми же событиями.

Затем вы можете использовать функцию (приемник) для обновления в соответствии с сигналом Sequence модель отправляет (post_save, pre_save, pre_delete и т.д ...).

Вы не должны переопределять save или delete для этого.Ваша логика включает изменения в более чем одном экземпляре, и вы должны сохранять и удалять относительно одного экземпляра.

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

Вы найдете очень хороший пример в документации.

https://docs.djangoproject.com/en/2.1/ref/models/expressions/#f-expressions

Обновление:

Хорошо, в исходном ответе я указал путь, теперьЯ покажу вам все это, я надеялся, что вы сможете понять это сами.

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

Это не неправильный подход, вы использовали неправильный сигнал / реализацию;).

В соответствии с вашими требованиями, я могу сказать, что есть соответствие:

update sequence instance (save)    --->    do not change indices 
delete sequence instance           --->    update indices  
create sequence instance           --->    add incremented index

Итак, у нас есть сигнал delete, и у нас также есть сигнал post_save , который получает в качестве третьегоаргумент логический, указывающий, был ли экземпляр создан или только что обновлен (Вы прочитали ссылку, которой я с вами поделился?).

Затем ...

Обновление индексов при удалении Sequenceэкземпляр:

@receiver(delete, sender=Sequence)
def deletion_handler(sender, instance, **kwargs):
    # Since number is incremental we only must update
    # those that are after the instance being deleted.
    number = instance.number
    sequences_for_update = Sequence.objects.filter(number__gt=number)
    # Decrement 1 to all sequences after number. No for loop.
    sequences_for_update.update(number=F('number') - 1)

Обновление индексов при создании нового экземпляра

@receiver(post_save, sender=Sequence)
def creation_handler(sender, instance, created, **kwargs):
    if created:
        # We only care about created instances (this avoid the infinite
        # loop you're talking about).
        # Now take the last number.
        instance.number = Sequence.objects.aggregate(last=Max('number'))['last'] + 1
        instance.save()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...