Как сделать эту специальную проверку многих полей с помощью Django ORM? - PullRequest
1 голос
/ 21 марта 2010

У меня есть следующая модель:

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 пуст в save(). Более того, Journey.id еще не существует. Я не пробовал django.db.models.signals.post_save, но предположил, что он не удастся, потому что Journey.route также пуст (когда это все равно заполняется?) Я вижу решение в django.db.models.signals.m2m_changed, но есть много шагов (тысяч), и я хочу избежать выполнения операции для каждого из них.

Ответы [ 2 ]

0 голосов
/ 21 марта 2010

В конце концов мне пришлось написать валидацию для каждой формы, создающей этот объект. Решение Кнутина было бы замечательно, но я запускаю 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 отображаются в качестве обратной связи для пользователя при отправке формы.

0 голосов
/ 21 марта 2010

Если вы используете новейший и лучший Django, взгляните на это http://docs.djangoproject.com/en/dev/ref/models/instances/#id1

В принципе, модели можно проверять так же, как формы. Хотя я никогда не использовал его сам, это выглядит как то, что вы пытаетесь сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...