【问题标题】:Change other objects inside model's custom save method in django在 django 中更改模型的自定义保存方法中的其他对象
【发布时间】:2019-02-06 19:53:11
【问题描述】:

嗯,我有两个 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 内部),这将对这个对象执行相同的操作。

这是解决问题的好方法吗? Django 有一些我可能不知道的特质,以后可能会咬我。我应该使用信号吗?有存档吗?感谢您的帮助!

【问题讨论】:

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


    【解决方案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 对象的顺序。

    【讨论】:

    • 你是对的,使用order_with_respect_to 是最好的方法。我必须对我的 api 进行一些更改才能使其工作,但现在它工作正常,谢谢!
    猜你喜欢
    • 2019-10-18
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2017-07-13
    • 2020-08-01
    • 2021-12-19
    相关资源
    最近更新 更多