代码之家  ›  专栏  ›  技术社区  ›  Bite code

如何使用django orm进行此特殊的许多字段验证?

  •  1
  • Bite code  · 技术社区  · 15 年前

    我有以下型号:

    class Step(models.Model):
    
        order = models.IntegerField()
        latitude = models.FloatField()
        longitude = models.FloatField()
        date = DateField(blank=True, null=True)
    
    
    class Journey(models.Model):
    
        boat = models.ForeignKey(Boat)
        route = models.ManyToManyField(Step)
        departure = models.ForeignKey(Step, related_name="departure_of", null=True)
        arrival = models.ForeignKey(Step, related_name="arrival_of", null=True)
    

    我想执行以下检查:

            # If a there is less than one step, raises ValidationError.
    
            routes = tuple(self.route.order_by("date"))
    
            if len(routes) <= 1:
                raise ValidationError("There must be at least two setps in the route")
    
            # save the first and the last step as departure and arrival
            self.departure = routes[0]
            self.arrival = routes[-1]
    
            # departure and arrival must at least have a date
            if not (self.departure.date or self.arrival.date):
                raise ValidationError("There must be an departure and an arrival date. "
                                      "Please set the date field for the first and last Step of the Journey")
    
            # departure must occurs before arrival    
            if not (self.departure.date > self.arrival.date):
                raise ValidationError("Departure must take place the same day or any date before arrival. "
                                      "Please set accordingly the date field for the first and last Step of the Journey")
    

    我试图通过超载来做到这一点。 save() . 不幸的是, Journey.route 在中为空 保存() . 另外, Journey.id 还不存在。我没试过 django.db.models.signals.post_save 但是假设它会失败,因为 旅程.路线 也是空的(还是什么时候填的?).我看到一个解决方案 django.db.models.signals.m2m_changed 但是有很多步骤(几千个),我想避免对每一个步骤执行操作。

    2 回复  |  直到 15 年前
        1
  •  0
  •   knutin    15 年前

    如果你在经营最新最棒的Django,看看这个 http://docs.djangoproject.com/en/dev/ref/models/instances/#id1

    基本上,可以用与表单相同的方式验证模型。虽然我自己从来没有用过它,但它看起来很适合你想做的事情。

        2
  •  0
  •   Bite code    15 年前

    最后,我必须为创建这个对象的每个表单编写一个验证。克努丁的解决方案会很好,但我运行django 1.1。

    不管怎样,Django让你很容易过载管理验证,所以我做到了:

    class JourneyAdminForm(forms.ModelForm):
    
        class Meta:
            model = Journey
    
        def clean_route(self):
            """
                Ensure a Journey includes at least 2 dated steps, 
                departure starting before arrival.
            """
    
            # must use getlist as self.data is not a dict but a querydict
            routes = self.data.getlist("route")
    
            if len(routes) <= 1:
                raise ValidationError("There must be at least two setps in the route")
    
            departure = Step.objects.get(id=routes[0])
            arrival = Step.objects.get(id=routes[-1])
            self.data["departure"] = departure.id
            self.data["arrival"] = arrival.id
    
    
            if not (departure.date and arrival.date):
                raise ValidationError("There must be an departure and an arrival date. "
                                      "Please set the date field for the first and last Step of the Journey")
    
            if not (departure.date <= arrival.date):
                raise ValidationError("Departure must take place the same day or any date before arrival. "
                                      "Please set accordingly the date field for the first and last Step of the Journey")
    
            return self.cleaned_data["route"]
    
    class JourneyAdmin(admin.ModelAdmin):
    
        exclude = ("arrival", "departure")
        form = JourneyAdminForm
    
    admin.site.register(Journey, JourneyAdmin)
    

    另外,在提交表单时,validationError消息将显示为用户的反馈。