Django CreateView提交评分时出现grader_id非空约束失败报错
问题根因
抛出NOT NULL constraint failed: auctions_grade.grader_id是因为Grade模型的grader外键设置了非空约束,但提交表单创建Grade记录时,没有给这个字段赋值,数据库写入时校验失败。
当前视图代码存在几个直接触发问题的错误:
- 重写的
get方法破坏了CreateView的内置逻辑,传入模板的是表单类而非实例化的表单对象,定义的user、grades、editable变量均未传入上下文,属于无效代码 - 没有在表单保存前注入请求相关的自动赋值字段——
grader(当前登录用户)、hw_upload(被评分的作业对象)这类不需要用户填写的非空外键,完全没有赋值逻辑 get_success_url方法存在缩进错误,会直接触发语法异常- 模板路径配置不一致,类属性里写的是
grading.html,手动render时用的是auctions/grading.html
修复方案
1. 重构GradeView视图
直接删除冗余的get方法重写,利用CreateView内置的表单处理逻辑,通过重写form_valid方法给非用户填写字段赋值,同时加上登录校验避免匿名用户访问:
from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic.edit import CreateView from django.urls import reverse_lazy from .models import Grade, Hw_upload from .forms import Hw_gradeForm class GradeView(LoginRequiredMixin, CreateView): model = Grade template_name = "auctions/grading.html" form_class = Hw_gradeForm def get_success_url(self): return reverse_lazy('homework_upload', args=(self.object.hw_upload.id,)) def form_valid(self, form): # 暂不提交数据库,先给自动填充字段赋值 grade = form.save(commit=False) # 绑定评分人为当前登录用户 grade.grader = self.request.user # 从URL参数获取待评分的作业对象,绑定外键 target_hw = Hw_upload.objects.get(pk=self.kwargs["hw_pk"]) grade.hw_upload = target_hw # 自动从作业对象同步关联的课程、模块、活动字段,无需手动传参 grade.course_grade = target_hw.course_hw_upload grade.module_grade = target_hw.module_hw_upload grade.activity_grade = target_hw.activity grade.graded = True # 写入数据库 grade.save() return super().form_valid(form)
2. 调整路由配置
因为代码里从URL参数取hw_pk获取待评作业,需要在urls.py里对应配置参数:
from django.urls import path from . import views urlpatterns = [ # 其余路由省略 path("grade/<int:hw_pk>/", views.GradeView.as_view(), name="grade_homework"), ]
在作业详情页跳转评分入口时,传入对应作业ID即可:
<a href="{% url 'grade_homework' hw.pk %}" class="btn btn-primary">提交评分</a>
3. 可选权限校验
如果需要限制只有教授角色可以评分,可以再加UserPassesTestMixin做权限判断,避免学生账号访问评分接口:
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin class GradeView(LoginRequiredMixin, UserPassesTestMixin, CreateView): # 其余代码不变 def test_func(self): # 只允许教授角色用户访问,根据你自己的用户角色字段调整判断逻辑即可 return self.request.user.is_professor
内容的提问来源于stack exchange,提问作者CVilla90
相关产品推荐
相关产品推荐

