django模型中的自定义保存方法
Posted
技术标签:
【中文标题】django模型中的自定义保存方法【英文标题】:Custom save method in django model 【发布时间】:2019-10-18 05:11:01 【问题描述】:我已经为模型编写了一个自定义保存方法,以防止保存无效数据,但是当我想通过管理员更新对象时(只是为了更改一些属性),我得到了一个断言错误
我的模特:
class Segment(CoreModel):
departure = models.ForeignKey(Place, on_delete=models.CASCADE, limit_choices_to=limit_choices_segment,
related_name='departures')
destination = models.ForeignKey(Place, on_delete=models.CASCADE, limit_choices_to=limit_choices_segment,
related_name='arrivals')
distance = models.FloatField(help_text='Distance between places in "km"!', null=True, blank=True,
validators=[property_positive_value])
duration = models.FloatField(help_text='Transfer duration (hours)', null=True, blank=True,
validators=[property_positive_value])
cost = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True,
help_text='Price for a transfer! Currency: "UAH"!',
validators=[property_positive_value])
route = models.ForeignKey(Route, on_delete=models.CASCADE, related_name='segments')
def __str__(self):
return '-'.format(self.departure, self.destination)
def save(self, *args, **kwargs):
assert self.departure.role not in (Place.DISTRICT, Place.REGION), (
"Departure couldn't be Region or District")
assert self.destination.role not in (Place.DISTRICT, Place.REGION), (
"Destination couldn't be Region orDistrict")
assert self.destination != self.departure, "Departure couldn't be equal to Destination"
assert self.route.segment_validate(departure=self.departure, destination=self.destination), (
'Impossible to add the segment, please check the route!')
if self.distance is not None:
assert self.distance > 0, "Distance couldn't be less or equal to '0'!"
if self.duration is not None:
assert self.duration > 0, "Duration couldn't be less or equal to '0'!"
if self.cost is not None:
assert self.cost > 0, "Cost couldn't be less or equal to '0'!"
super(Segment, self).save(*args, **kwargs)
验证方法:
def segment_validate(self, departure, destination):
segments = self.segments.all()
if segments:
for segmnet in segments:
same_departure = segmnet.departure == departure
same_destination = segmnet.destination == destination
if ((same_departure and same_destination) or
same_departure or same_destination):
return False
if segments.latest('created').destination != departure:
return False
return True
错误在这里:
assert self.route.segment_validate(departure=self.departure, destination=self.destination), (
'Impossible to add the segment, please check the route!')
但我没有更改 departure
和 destination
你能帮我避免这个错误吗?
【问题讨论】:
好吧,既然您已经添加了该细分,那么该细分现在与自身发生冲突! @WillemVanOnsem,您知道如何解决吗?因为我不能跳过导致错误的验证方法? 顺便问一下self.segments
在这里做什么?看起来这是 Route
模型的验证器?
@WillemVanOnsem,是的,它来自 Route
模型的验证器,它检查是否可以向路线添加新段
您在保存中的断言将导致用户出现 500 个错误(至少如果它们发生在管理员那里),最好在您的表单代码中进行验证,并编写一个 Model.clean(..)
引发的方法ValidationErrors
处理您在保存中所做的验证...(文档:docs.djangoproject.com/en/dev/ref/models/instances/… 相关 SO ***.com/questions/8771029/…)
【参考方案1】:
这是一个问题的原因是因为如果您已经保存了一个段,现在您询问数据库中是否有一个段具有 same department
或 destination
。如果你没有更新destination
的department
,那么当然有:那个特定的段。
我们可以从中排除我们的segment
,假设它存在,用:
from django.db.models import Q
def segment_validate(self, departure_pk, destination_pk, segment_pk):
segments = self.segments.exclude(pk=segment_pk)
if not segments.filter(
Q(departure_id=departure_pk) |
Q(destination_id=destination_pk)
).exists():
return False
if segment_pk is None:
return segments.latest('created').destination_id != departure_pk
return True
因此,我们通过以下方式进行检查:
assert self.route.segment_validate(<b>self.departure_id, self.destination_id, self.pk</b>), ('Impossible to add the segment, please check the route!')
【讨论】:
以上是关于django模型中的自定义保存方法的主要内容,如果未能解决你的问题,请参考以下文章