Django使用unique_together时如何让双时段选项阻塞单时段重复提交
Django 学生时段申请冲突校验实现方案
你可以通过重写模型的自定义校验方法实现需求,具体实现如下:
步骤1:为模型添加自定义校验逻辑
首先导入校验异常类,之后在你的RequestAStudent模型中重写clean方法,实现冲突判断:
from django.core.exceptions import ValidationError class RequestAStudent(models.Model): PERIODS=( ('Academic Network 1', 'Academic Networking 1'), ('Academic Network 2', 'Academic Networking 2'), ('Both Periods', 'Both Periods'), ) MARK=( ('None', 'None'), ('Present', 'Present'), ('Tardy', 'Tardy'), ('X', 'X'), ('Absent', 'Absent'), ) # 原有字段保持不变 student = models.ForeignKey(Student, on_delete= models.CASCADE) date_created = models.DateField(auto_now_add=True, null=True) Requesting_Teacher = models.ForeignKey(AdvisoryTeacher, on_delete= models.CASCADE) Period = models.CharField(max_length=18, null=True, choices = PERIODS) teacher = models.ForeignKey(Teacher, verbose_name='Advisory Teacher',default="None", on_delete= models.CASCADE) date_requested = models.CharField(max_length=200, verbose_name='Date for Student Request (Use format MMDDYY)', default="2021-11-04",null=True) attendance = models.CharField(verbose_name='UPDATE ATTENDANCE HERE!',max_length=18, default="None",choices = MARK) owner = models.IntegerField("Request Owner", blank=False, default=1) def clean(self): # 查询同学生、同申请日期下的所有已有申请,排除当前正在编辑的记录本身 existed_records = RequestAStudent.objects.filter( student=self.student, date_requested=self.date_requested ).exclude(pk=self.pk) # 核心需求逻辑:提交单时段申请时,检查是否已有全时段申请 if self.Period in ['Academic Network 1', 'Academic Network 2']: if existed_records.filter(Period='Both Periods').exists(): raise ValidationError('该学生当前申请日期已存在全时段申请,无法提交单时段申请') # 可选补充逻辑:提交全时段申请时,检查是否已有单时段申请,避免冲突 if self.Period == 'Both Periods': if existed_records.filter(Period__in=['Academic Network 1', 'Academic Network 2']).exists(): raise ValidationError('该学生当前申请日期已存在单时段申请,无法提交全时段申请') def __str__(self): return "" + str(self.student) + ", Teacher: " + str(self.owner) class Meta: unique_together = ["student", "Period", "date_requested"]
步骤2:确保校验逻辑触发
- 如果你使用
ModelForm处理前端表单提交,无需额外操作,Django会自动调用clean方法完成校验,错误信息会直接返回到表单页面 - 如果你直接调用模型
save方法操作数据(如shell操作、后台脚本),需要在save前手动调用实例.full_clean()触发校验,也可以重写save方法自动触发:
def save(self, *args, **kwargs): self.full_clean() super().save(*args, **kwargs)
补充说明
原有unique_together配置可以保留,它仍然负责拦截同一时段的重复申请,和新增的自定义校验逻辑互不冲突。
内容的提问来源于stack exchange,提问作者Mark Young
相关产品推荐
相关产品推荐

