You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Admin带Inline模型的批量保存验证方案

Django嵌套Admin测验系统验证实现

要实现你需要的验证逻辑(每个问题至少一个有效答案、每个问题至少一个正确答案),我们需要在QuizAdmin中重写save_formset方法,因为嵌套内联的数据是通过表单集(formset)处理的。以下是修改后的完整代码:

修改后的admins.py

from quiz.models import *
from django.contrib import admin
from nested_inline.admin import NestedStackedInline, NestedModelAdmin, NestedTabularInline
from django.core.exceptions import ValidationError


class AnswerInLine(NestedTabularInline):
    """ Делаем вложенную модель в админке"""
    model = QuizAnswer
    extra = 1


class QuestionInLine(NestedStackedInline):
    """ Делаем вложенную модель в админке"""
    model = QuizQuestion
    extra = 2
    inlines = [AnswerInLine]


class QuizAdmin(NestedModelAdmin):
    model = Quiz
    inlines = [QuestionInLine]
    readonly_fields = ('owner', 'created_at', 'updated_at')

    def save_model(self, request, obj, form, change):
        if not obj.pk:
            obj.owner = request.user
        super().save_model(request, obj, form, change)

    def save_formset(self, request, form, formset, change):
        # 遍历所有问题表单,跳过标记为删除的问题
        for question_form in formset.forms:
            if not question_form.cleaned_data.get('DELETE', False):
                # 获取当前问题对应的答案表单集
                answer_formset = question_form.inlines[0]
                # 过滤无效答案:排除标记删除或文本为空的答案
                valid_answers = [
                    answer_form for answer_form in answer_formset.forms 
                    if not answer_form.cleaned_data.get('DELETE', False) 
                    and answer_form.cleaned_data.get('text', '').strip()
                ]
                
                # 验证:问题必须至少有一个有效答案
                if len(valid_answers) == 0:
                    question_text = question_form.cleaned_data.get('question', 'неизвестный вопрос')
                    raise ValidationError(f"Вопрос '{question_text}' должен иметь хотя бы один вариант ответа.")
                
                # 验证:问题必须至少有一个正确答案
                has_correct_answer = any(
                    answer_form.cleaned_data.get('is_correct', False) 
                    for answer_form in valid_answers
                )
                if not has_correct_answer:
                    question_text = question_form.cleaned_data.get('question', 'неизвестный вопрос')
                    raise ValidationError(f"Вопрос '{question_text}' должен иметь хотя бы один правильный ответ.")
        
        # 执行默认的表单集保存逻辑
        super().save_formset(request, form, formset, change)


class CategoryAdmin(admin.ModelAdmin):
    list_display = ("id", 'title')
    list_display_links = ('id', 'title')
    search_fields = ('title',)


admin.site.register(Quiz, QuizAdmin)

代码说明

  • 导入ValidationError:用于抛出验证错误,错误信息会直接显示在Admin页面顶部,引导用户修正问题。
  • save_formset方法重写:这是处理嵌套内联表单验证的核心位置:
    1. 遍历每个问题表单,跳过已经标记为删除的问题;
    2. 获取当前问题关联的答案表单集,过滤掉无效的答案(标记删除或文本为空的条目);
    3. 检查有效答案数量,确保每个问题至少有一个非空答案;
    4. 检查是否存在至少一个标记为正确的答案;
  • 错误提示优化:错误信息中包含具体的问题文本,方便用户快速定位需要修正的问题。

内容的提问来源于stack exchange,提问作者Seliverstov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 19:50:23