Python django模型中的自定义保存方法

Python django模型中的自定义保存方法,python,django,django-models,Python,Django,Django Models,为了防止保存无效数据,我为模型编写了一个自定义保存方法,但是当我想通过admin更新对象(只是为了更改一些属性)时,我得到了一个assert错误 我的模型: class Segment(CoreModel): departure = models.ForeignKey(Place, on_delete=models.CASCADE, limit_choices_to=limit_choices_segment, rela

为了防止保存无效数据,我为模型编写了一个自定义保存方法,但是当我想通过admin更新对象(只是为了更改一些属性)时,我得到了一个assert错误

我的模型:

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!')
但是我没有改变出发地点和目的地
您能帮我避免这个错误吗?

这是一个问题的原因是,如果您已经保存了一个段,那么现在您会询问数据库中是否有一个段具有相同的
部门
目的地
。如果您没有更新
目的地
部门
,那么当然有:该特定部分

我们可以从中排除我们的
,前提是它存在,包括:

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
从django.db.models导入Q
def段验证(自我、出发、目的地、段):
段=自.段.排除(pk=段\段pk)
如果不是,请选择“分段”过滤器(
Q(出发号=出发号)|
Q(目的地\标识=目的地\主键)
).exists():
返回错误
如果段_pk为无:
返回段。最新('created')。目的地id!=出发地点
返回真值
因此,我们通过以下方式对此进行检查:

assert self.route.segment_validate(self.departure_id, self.destination_id, self.pk), ('Impossible to add the segment, please check the route!')

assert self.route.segment\u validate(self.example\u id,self.destination\u id,self.pk),(“无法添加段,请检查路线!”)
既然您已经添加了该段,该段现在与自身存在冲突@威廉·瓦农森,你知道怎么修吗?因为我不能跳过导致错误的验证方法?顺便问一下,
self.segments
在这里做什么?看起来这是一个
路由
模型的验证器?@WillemVanOnsem,是的,它是一个
路由
模型的验证器,它检查是否可以向路由添加新的段。您在save中的断言将导致500个用户错误(至少如果是从管理员那里发生的),最好在表单代码中进行验证,然后编写一个
Model.clean(..)
方法,该方法将引发
ValidationErrors
以处理在save中执行的验证。。。(文件:相关SO)