django проверяет значения для вычисления

#django #django-models #django-views #calculation #django-validation

#django #django-модели #django-представления #вычисление #django-проверка

Вопрос:

Привет!

Мне нужно выполнить несколько простых вычислений отфильтрованных данных в моем представлении django. Это отлично работает при наличии значений в выбранном фильтре. Если значение равно 0 или отсутствует, я получаю сообщение об ошибке сервера, и сайт завершает работу. Поэтому мне нужен валидатор, чтобы убедиться, что заданное значение не равно 0, а не None.

(моя попытка внизу) В настоящее время, если добавлен валидатор, он выдает мне сообщение о том, что объект ‘float’ не вызывается, даже до перехода к опции / шаблону фильтра.

И: в моей модели есть m2m для модели, из которой я получаю значения. Для каждого значения можно выбрать единицу измерения, и я хочу вычислить, только если единицы измерения идентичны, в противном случае я хочу получить предупреждение.

Кто-нибудь знает, как этого добиться? Или где искать?

Любая помощь приветствуется! 🙂

 # validators.py

def validate_values(value):
    if value == 0:
        raise ValidationError(_('One of the given values is 0 or empty and the calculation therefore cannot be proceeded.'),
                              code='notinrange')
 
 # views.py

def process_mass_intensity(request):
    plants = Plant.objects.all()

    myFilter = PlantsNameFilter(request.GET, queryset=plants)
    plants = myFilter.qs

    total_m = plants.aggregate(Sum('used_in_plant__value'))['used_in_plant__value__sum']

    product_m = plants.aggregate(product_mass=Sum('used_in_plant__value',
                                                  filter=Q(used_in_plant__input_or_output='OUT')))['product_mass'](validators=[validate_values])

    pmi = (total_m / product_m)(validators=[validate_values])

    context = {"plants": plants, "myFilter": myFilter, "total_m": total_m, "product_m": product_m, "pmi": pmi}
    return render(request, 'kpi/process_mass_intensity.html', context)
 
 # models.py

class Plant(models.Model):
    name = models.CharField(
        max_length=200
    )
    used_xducts = models.ManyToManyField(
        Xduct,
        through="UsedXduct",
        blank=True,
        related_name="used_in_plant"
    )



class UsedXduct(models.Model):
    plant = models.ForeignKey(
        Plant,
        on_delete=models.PROTECT,
        related_name="used_in_plant"
    )
    xduct = models.ForeignKey(
        Xduct,
        on_delete=models.PROTECT,
        related_name="xduct"
    )
    value = models.FloatField()
    quantity = models.ForeignKey(
        Quantity,
        on_delete=models.PROTECT
    )
    unit = models.ForeignKey(
        Unit,
        on_delete=models.PROTECT
    )
 

Ответ №1:

Валидаторы применяются на уровне полей. Здесь вы также можете использовать MinValueValidator вместо пользовательской функции проверки. Давайте разберем это пополам.

Причина, по которой вы, вероятно, получаете эту ошибку, заключается в том, что вы умножаете значение (точнее, значение с плавающей точкой) раз (validators=[validate_values]) , которое является функцией. На самом деле это не имеет смысла.

Вместо этого вы хотели бы поместить свои валидаторы в объявление поля в вашей модели. Итак:

 from django.core.validators import MinValueValidator

class UsedXduct(models.Model):
    plant = models.ForeignKey(
        Plant,
        on_delete=models.PROTECT,
        related_name="used_in_plant"
    )
    xduct = models.ForeignKey(
        Xduct,
        on_delete=models.PROTECT,
        related_name="xduct",
        validators=[MinValueValidator(0)]
    )
    value = models.FloatField()
    quantity = models.ForeignKey(
        Quantity,
        on_delete=models.PROTECT,
        validators=[MinValueValidator(0)]
    )
    unit = models.ForeignKey(
        Unit,
        on_delete=models.PROTECT
    )
 

В качестве альтернативы, чтобы не выполнять проверку при создании модели, вы можете просто запустить свою функцию проверки в самом представлении:

 def process_mass_intensity(request):
    plants = Plant.objects.all()

    myFilter = PlantsNameFilter(request.GET, queryset=plants)
    plants = myFilter.qs

    total_m = plants.aggregate(Sum('used_in_plant__value'))['used_in_plant__value__sum']

    product_m = validate_values(plants.aggregate(product_mass=Sum('used_in_plant__value', filter=Q(used_in_plant__input_or_output='OUT')))['product_mass'])

    pmi = validate_values(total_m / product_m)

    context = {"plants": plants, "myFilter": myFilter, "total_m": total_m, "product_m": product_m, "pmi": pmi}
    return render(request, 'kpi/process_mass_intensity.html', context)
 

Надеюсь, это поможет, дайте мне знать, если у вас есть вопросы.

Комментарии:

1. К сожалению, это не работает для меня. Я все еще получаю сообщение об ошибке, что NoneType не поддерживается. (вне модели) Возможно, попытка проверки не работает для меня здесь. Есть ли у вас другая идея, как я мог бы добиться того, чтобы я получал предупреждающее сообщение о том, что вычисление не может быть выполнено из-за пропущенного значения или несоответствующей единицы измерения вместо ошибки сервера?