如果存在相关对象,防止更改字段?

时间:2015-11-02 14:25:06

标签: python django django-admin django-validation

我的Django应用程序中有两个模型:

class Survey(models.Model):
    survey_type = models.CharField(max_length=1, choices=SURVEY_TYPES)

class Response(models.Model):
    survey = models.ForeignKey(Survey)
    response = models.TextField()

当调查的组织者创建调查时,他们可以指定类型。一旦第一个响应出现,我就不希望组织者能够使用站点管理员更改类型(因为响应模型中的自由文本响应字段会改变含义)。

我已经研究过使用验证器,但据我所知,它们的目的是在表单上操作,而不是在要保存的对象上。我找不到任何支持在其中执行数据库查询。

我也考虑过覆盖save方法,但据我可以确定的是,它不会被用于验证(我宁愿不在我的模型中添加任何逻辑)

我在其他框架中这样做的方式就是在ORM上面引入一些层,允许我引入业务规则。请告知 - 这里的最佳做法是什么?

2 个答案:

答案 0 :(得分:2)

您实际上可以使用模型级验证:

class Survey(models.Model):
    survey_type = models.CharField(max_length=1, choices=SURVEY_TYPES)

    def __init__(self, *args, **kwargs):
        super().__init__(self, *args, **kwargs)
        self._old_survey_type = self.survey_type

    def clean(self):
        if (self.survey_type != self._old_survey_type) \
                and survey_typeself.response_set.exists():
            raise ValidationError('Cannot modify the type of a started survey') 

但请注意,保存对象时不会自动调用Model.clean。当ModelForm被验证时(因此也在管理员中),它会发生,但是否则你必须检查它是否存在或自己调用它。

答案 1 :(得分:0)

survey模型中的responseResponse字段设为唯一的 unique together喜欢这样:

class Response(models.Model):
    survey = models.ForeignKey(Survey)
    response = models.TextField()

    class Meta:
        unique_together = (("survey", "response"),)