Django模型clean方法不生效,如何自定义抛出指定验证错误?
Django ConnectedRoute模型clean方法不生效的问题修复
几个关键遗漏点及修复方案
1. 漏了导入ValidationError
你代码里没导入ValidationError类,这会导致抛出异常时直接报错,没法正常触发验证提示,得补上:
from django.core.exceptions import ValidationError
2. 模型save默认不触发clean
Django模型的save()方法不会自动调用clean(),得手动调用full_clean()(它会依次执行字段验证、自定义clean逻辑、唯一约束验证)。给模型加个save方法:
def save(self, *args, **kwargs): self.full_clean() super().save(*args, **kwargs)
3. 计数逻辑没排除当前实例(更新时会算错)
现在的计数逻辑在修改已有记录时,会把当前实例本身也算进总数里,导致误判。得在查询时排除当前实例(如果是已存在的记录):
def clean(self): super().clean() # 先调用父类clean,保留默认逻辑 if self.bus_stop_1 == self.bus_stop_2: raise ValidationError('两个公交站点不能相同') # 构建查询集,排除当前实例(更新场景) stop1_query = ConnectedRoute.objects.filter(bus_stop_1=self.bus_stop_1) stop2_query = ConnectedRoute.objects.filter(bus_stop_2=self.bus_stop_2) if self.pk: # pk存在说明是更新操作 stop1_query = stop1_query.exclude(pk=self.pk) stop2_query = stop2_query.exclude(pk=self.pk) total = stop1_query.count() + stop2_query.count() if total > 4: raise ValidationError('单个公交站点最多只能关联4条线路')
4. Admin后台要确保触发验证
如果是在Django Admin里操作,默认Admin会触发验证,但要是你自定义了save_model方法,得手动加full_clean():
from django.contrib import admin from .models import ConnectedRoute class ConnectedRouteAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): obj.full_clean() super().save_model(request, obj, form, change) admin.site.register(ConnectedRoute, ConnectedRouteAdmin)
完整修复后的代码
from django.db import models from django.core.exceptions import ValidationError # 这里要确保导入你的BusStop模型 from .models import BusStop class ConnectedRoute(models.Model): bus_stop_1 = models.ForeignKey( BusStop, on_delete=models.CASCADE, related_name='stop1') bus_stop_2 = models.ForeignKey( BusStop, on_delete=models.CASCADE, related_name='stop2') distance = models.FloatField(blank=True, null=True) time = models.TimeField(blank=True, null=True) def clean(self): super().clean() if self.bus_stop_1 == self.bus_stop_2: raise ValidationError('两个公交站点不能相同') stop1_query = ConnectedRoute.objects.filter(bus_stop_1=self.bus_stop_1) stop2_query = ConnectedRoute.objects.filter(bus_stop_2=self.bus_stop_2) if self.pk: stop1_query = stop1_query.exclude(pk=self.pk) stop2_query = stop2_query.exclude(pk=self.pk) total_connections = stop1_query.count() + stop2_query.count() if total_connections > 4: raise ValidationError('单个公交站点最多只能关联4条线路') def save(self, *args, **kwargs): self.full_clean() super().save(*args, **kwargs)
内容的提问来源于stack exchange,提问作者Abhijith M R
相关产品推荐
相关产品推荐

