首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从外键的反向验证对象

如何从外键的反向验证对象
EN

Stack Overflow用户
提问于 2019-12-17 16:24:05
回答 2查看 339关注 0票数 1

我有两个通过ForeignKey连接在一起的对象。

代码语言:javascript
运行
复制
class Question(models.Model):
    text = models.Charfield()

class AnswerOption(models.Model):
    text = models.Charfield()
    question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name="options")

当在管理界面中创建Question时,我为AnswerOptions使用了一个内联表单,以便同时创建它们。我想在Question上执行一些验证,它需要访问新的AnswerOptions才能做出决定。

我已经向clean添加了一个Question方法,但是options属性是空的。

验证Question的正确方法是什么?

编辑清楚地表明,Question需要访问AnswerOptions才能验证所有内容。

编辑添加了对在管理界面中使用InlineForm for AnswerOptions的显式引用。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-12-19 13:58:19

这就是我发现的:

在管理接口中创建内联表单时,Django创建一个Formset来处理多个表单。(示例这里与我的用例相同)

Formsets和其他窗体一样有一个clean()方法,它们有一个forms属性来访问子窗体。就像普通表单一样,它们有一个instance属性,该属性引用“基类”,而单个表单具有一个instance属性,它为您提供新提交的数据的一个实例。

把这一切结合在一起:

代码语言:javascript
运行
复制
# models.py

class Question(models.Model):
    text = models.Charfield()

class AnswerOption(models.Model):
    text = models.Charfield()
    question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name="options")

# admin.py

from django.contrib import admin
from django.forms.models import BaseInlineFormSet

class AnswerOptionFormset(BaseInlineFormset):
    def clean(self):
        super().clean() # See note in docs about calling this to check unique constraints

        #self.instance -> Question, with all the newly submitted, and validated, data.
        #self.forms -> iterator over all the submitted AnswerOption forms
        #for f in self.forms:
        #    f.instance -> instance of AnswerOption containing the new validated data

        #Note: self.instance.options will refer to the previous AnswerOptions

        #raise ValidationError for anything that is wrong.
        #It is also possible to modify the data in self.instance or form.instance instead.


class AnswerOptionInline(admin.TabularInline):
    formset = AnswerOptionFormset # note formset on AnswerOption NOT QuestionAdmin 


class QuestionAdmin(admin.ModelAdmin):
    inlines = [AnswerOptionInline]
票数 1
EN

Stack Overflow用户

发布于 2019-12-17 21:30:04

我会通过Django表单来完成这个任务,它有一个更健壮的验证接口。表单上的clean方法是进行这种类型验证的地方。

代码语言:javascript
运行
复制
# forms.py 

from django import forms
from .models import Question

class QuestionForm(forms.Form):
    text = models.Charfield()

    class Meta:
        model = Question

    def clean(self):
        options = self.cleaned_data['options']
        if not option.are_ok:
          raise forms.ValidationError
代码语言:javascript
运行
复制
# admin.py

from django import admin
from .forms import QuestionForm


class QuestionAdmin(admin.ModelAdmin):
    form = QuestionForm

...

来自医生们

表单子类的clean()方法可以执行需要访问多个表单字段的验证。这是您可能会进行检查的地方,例如“如果字段A被提供,字段B必须包含一个有效的电子邮件地址”。如果愿意,此方法可以返回一个完全不同的字典,该字典将用作cleaned_data。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59378296

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档