带有外键的 django 自定义表单验证

Posted

技术标签:

【中文标题】带有外键的 django 自定义表单验证【英文标题】:django custom form validation with foreign keys 【发布时间】:2012-10-05 23:58:50 【问题描述】:

我有以下型号:

class Computer(models.Model):
    ...

class Demo(models.Model):
    computers = models.ManyToManyField(Computer)
    ...

class Scenario(models.Model):
    demo = models.ForeignKey(Demo)
    ...

class Setting(models.Model):
    scenario = models.ForeignKey(Scenario)
    computer = models.ForeignKey(Computer)

基本上一个演示使用多台计算机。一个演示也有多个场景。每个场景都有一些设置,每个设置都配置一台计算机。

我的问题是在使用 django Admin 站点添加场景时,用户在下拉列表中选择了一个演示并为某些计算机配置了设置后,我需要验证设置中的计算机是否确实在演示。

我翻遍了 django 文档、在线网站,并尝试了所有我能想到的方法,但仍然无法完成这项工作。

我无法使用自定义表单验证,因为虽然我可以从场景表单中的 clean_data 获取“演示”对象,但我似乎无法访问随表单提交的设置。如果我通过覆盖“干净”来进行模型级别验证,那么只有在我更改场景时才有效,而不是在我添加新场景时有效,因为 computer_set 对于新场景是空的。

非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

您可以将自定义表单添加到您的 SettingInline(我从您的帖子中假设 SettingScenario 的内联)。

您提到您不能使用表单验证,但我看不出您需要访问所有其他设置的原因。如果您想访问其他设置(比如涉及所有提交设置的验证),我会覆盖 formset 本身。

class SettingForm(forms.ModelForm):
    class Meta:
        model = Setting

    def clean_computer(self):
        computer = self.cleaned_data.get('computer')
        if not self.instance.scenario.demo.computers.filter(computer=computer).count():
            raise forms.ValidationError("Computer not in demo")
        return computer

class SettingInline(admin.TabularInline):
    model = Setting
    form = SettingForm

【讨论】:

感谢您的建议。虽然这适用于编辑现有场景,但在添加新场景时不起作用。我得到了一个 DoesNotExist 异常。我猜是因为 self.instance 还不存在。 DoesNotExist 从何而来? self.instance 将永远存在;它可能没有PK,但它将是一个真实的实例。外键也应该存在..

以上是关于带有外键的 django 自定义表单验证的主要内容,如果未能解决你的问题,请参考以下文章

将带有外键的自定义标签呈现到模板问题中

Django 表单验证之自定义表单验证器

带有两个外键的 Django 保存表单

Django 和自定义表单验证

在自定义 Django 表单中验证和显示错误

看用Tornado如何自定义实现表单验证