Изменить другие объекты внутри пользовательского метода сохранения модели в Django - PullRequest
0 голосов
/ 06 февраля 2019

Ну, у меня есть две модели django для хранения Вопросов и Вопросников.Каждый вопрос находится внутри анкеты.У каждого Вопроса должно быть поле для хранения порядка, в котором он будет отображаться в анкете.Мои вопросы о том, как лучше всего обрабатывать изменения в порядке вопроса.

Код для моделей:

class Questionnaire(models.Model):
    name = models.CharField(max_length = 100)
    time_creation = models.DateTimeField(auto_now=True)


class Question(models.Model):
    questionnaire = models.ForeignKey(Questionnaire, related_name='questions', on_delete=models.CASCADE)
    text = models.TextField()
    order = models.IntegerField()

Один из способов, которым я думал об этом, был путемпереопределение метода сохранения для модели Вопроса, например:

def save(self, *args, **kwargs):
    all_questions = self.questionnaire.questions.all()
    if (self.order == None or self.order > len(all_questions)+1 or self.order == 0):
        self.order = len(all_questions)+1 # starts in 1
    else:
        previous = all_questions.filter(order=self.order)
        if len(previous)>0:
            p = previous[0]
            p.order = self.order+1
            p.save()
    super().save(*args, **kwargs)

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

Это хороший способ решить проблему?У Джанго есть несколько особенностей, о которых я мог не знать и мог бы укусить меня позже.Должен ли я использовать сигналы, может быть?Сделать сообщение сохранить?Спасибо за вашу помощь!

1 Ответ

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

Django предоставляет очень простой механизм с помощью мета-опций модели, а именно order_with_respect_to .Я полагаю, что его использование уже облегчит задачу:

class Question(models.Model):
    questionnaire = models.ForeignKey(Questionnaire)
    # ...
    class Meta:
        order_with_respect_to = 'questionnaire'

Это добавляет два метода к модели Questionnaire.Оба позволяют обрабатывать порядок объектов Question, используя список Question первичных ключей.

Получить заказ

questionnaire = Questionnaire.objects.get(id=1)
questionnaire.get_question_order()
[1, 2, 3]

Установить порядок

questionnaire.set_question_order([3, 1, 2])

Обратите внимание, что эта операция добавит столбец _order в базу данных и неявно установит ordering для ее использования.

Теперь вы можете реализовать всю дальнейшую бизнес-логику, манипулируя списком заказов.Просто примерный помощник для поиска порядка Question объекта:

questionnaire = Questionnaire.objects.get(id=1)
question_order = questionnaire.get_question_order()

question = Question.objects.get(foo='bar')
position = question_order.index(question.pk)

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

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