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方法重写:这是处理嵌套内联表单验证的核心位置:
- 遍历每个问题表单,跳过已经标记为删除的问题;
- 获取当前问题关联的答案表单集,过滤掉无效的答案(标记删除或文本为空的条目);
- 检查有效答案数量,确保每个问题至少有一个非空答案;
- 检查是否存在至少一个标记为正确的答案;
- 错误提示优化:错误信息中包含具体的问题文本,方便用户快速定位需要修正的问题。
内容的提问来源于stack exchange,提问作者Seliverstov
相关产品推荐
相关产品推荐

