在Django

时间:2019-02-06 19:53:12

标签: django python-3.x django-models

好吧,我有两个用于存储问题和问卷的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()

我想到的一种方法是重写Question模型的save方法,就像这样:

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()内部,我验证是否存在一个具有相同订单号的Question并将其增加,然后调用save(在save内部),对此对象将执行相同的操作。 / p>

这是解决问题的好方法吗? Django有一些我可能不了解的特性,后来可能会咬我。我应该使用信号吗?是否发布保存?谢谢您的帮助!

1 个答案:

答案 0 :(得分:1)

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对象的顺序。