Найти - Пользователи
Полная версия: Дополнительная проверка. Переопределение метода clean.
Начало » Django » Дополнительная проверка. Переопределение метода clean.
1
andrey16
Допустим есть следующий код:
def is_positive_decimal(value):
    '''Разрешены десятичные числа, с 2 знаками после запятой/точки
    '''
    strng = str(value.replace(',', '.')).split('.')
    if all(str(i).isdigit() for i in strng):
        if len(strng) > 2:
            raise ValidationError(u'много точек/запятых')
        elif len(strng) == 2 and len(strng[1]) != 2:
            raise ValidationError(
                u'Количество чисел после запятой должно быть равно 2')
        elif len(strng) == 2 and int(strng[0]) == int(strng[1]) == 0:
            raise ValidationError(u'Введите2 положительное число!')
    else:
        raise ValidationError(u'Введите3 положительное число!')
class Person(models.Model):
    name = models.CharField(max_length=50, verbose_name=u'Человек')
    balance = models.CharField(
        max_length=50, verbose_name=u'Сумма',
        validators=[is_positive_decimal])
        
    def __unicode__(self):
        return self.name

если через админку попробуем сохранить объект класса Theft с money='0-9', но т.к. он у нас не пройдет валидацию is_positive_decimal, нам соответствующим образом укажут на ошибку.
class Theft(models.Model):
    name = select2.fields.ForeignKey(
        Person, verbose_name='Человек', ajax=True,
        search_field='name',
        overlay=u"выбираем человека", js_options={'quiet_millis': 100,},)
    money = models.CharField(
        max_length=50, verbose_name=u'Сумма',
        validators=[is_positive_decimal])
    
    def save(self, *args, **kwargs):
        self.money = self.money.replace('.', ',')
        if len(str(self.money).split(',')) == 1:
            self.money += ',00'
        super(Theft, self).save(*args, **kwargs)

если мы модифицируем код следующим образом:
class Theft(models.Model):
    name = select2.fields.ForeignKey(
        Person, verbose_name='Человек', ajax=True,
        search_field='name',
        overlay=u"выбираем человека", js_options={'quiet_millis': 100,},)
    money = models.CharField(
        max_length=50, verbose_name=u'Сумма',
        validators=[is_positive_decimal])
    
    def save(self, *args, **kwargs):
        self.money = self.money.replace('.', ',')
        if len(str(self.money).split(',')) == 1:
            self.money += ',00'
        super(Theft, self).save(*args, **kwargs)
    
    def clean(self):
        if float(self.name.balance.replace(',', '.')) < \
                        float(self.money(',', '.')):
                    raise ValidationError(
                        u'Остаток на счете меньше указанной суммы')

… и попробуем сохраниться теперь объект с money='0-9', то Джанго уже не будет объяснять нам по-хорошему, а вывалится со следующей ошибкой
Exception Value:
invalid literal for float(): 0-9

как поправить ситуацию?
andrey16
проблема в том, что clean выполняется раньше, чем проверка заполнены ли поля и проходят ли они валидацию.
вопрос же глупый. но я никак из документации не могу понять где у меня ошибка
FishHook
Зачем деньги хранить как строку? Сделайте DecimalField, там есть max_digits и decimal_places.
andrey16
FishHook
Зачем деньги хранить как строку? Сделайте DecimalField, там есть max_digits и decimal_places.
это я знаю. но мне надо, чтобы можно было при вводе копейки от рублей отделялять хоть точкой, хоть запятой, а в базу сохранять с запятой.
но это меня сейчас не беспокоит.
меня интересует как заставить сначала проверять заполнены ли все поля, проходит ли поле с деньгами валидацию is_positive_decimal и уже только после всего этого выполнять все проверки из clean, дабы Джанго не вываливался с ошибкой.
FishHook
andrey16
это я знаю. но мне надо, чтобы можно было при вводе копейки от рублей отделялять хоть точкой, хоть запятой, а в базу сохранять с запятой.
Ну это вообще никак не дело модели какие-то там запятые от точек отделять. Все это делается в формах или в представлениях, но ни как не в модели.
Dr.Livsi
сделайте деньги в моделях правильно - как decimal. Т.е. и money и balance. Далее в класс формы пишете метод:
    def clean_money(self):
        money = self.cleaned_data['money']
        if self.name.balance < money:
            raise ValidationError(u'Остаток на счете меньше указанной суммы')
        return money
Он проверяет конкретно поле money.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB