django validate values for calculation

Hej!

I need to do some simple calculations of filtered data in my django view. This works just fine when having values in the chosen filter. If the value is 0 or None I get an server error and the site collpases. Therefore I need a validator to make sure the given value is not 0 and not None.

(my attempt is at the bottom) Currently if the validator is added it gives me the message that ‘float’ object is not callable, even before getting to the filter option/template.

And: in my model is a m2m to the model where I get the values from. For each value can a unit be chosen and I only want to calculate if the units are identical, otherwise I want to get a warning.

Does anyone knows how to achieve that? Or where to look?

Any help is appreciated! :slight_smile:

# 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
    )

This line looks odd to me. Are you trying to multiply those two values? If so, you need to use the multiplication operator (*) between the expressions. Python doesn’t recognize implicit multiplication between adjacent expressions.

I’m not sure where to put the validator I guess. Till now I only used validators in the model where I used it like:

value = models.IntegerField(validators=[validate_values]) 

I want a warning if total_m oder product_m are 0 or None, not to collapse the server.

And if the units are not the same.

What I was addressing was this error you identified.

That error is caused by this line, for the reason I mentioned in the previous response:

A validator is assigned as a validator on either a model field or a form field. However, since it is a callable, you can use it anywhere.
e.g.

(code doing stuff)
validate_values(some_value)
(more code doing stuff)

However, your validator doesn’t do what your ValidationError message says it’s going to do.

Your message implies that you can pass multiple values to it - but it doesn’t check multiple values. If you pass it a list, the list is never going to “==0”. It also doesn’t check to see if the value is None.

What you’re precisely trying to achieve here isn’t clear to me from this description.
What I would say in general is that you’re probably going to need to iterate through the related tables and do this within your code yourself. While you could probably write an ORM query to do the calculations that way, it’s not going to generate a warning on a mismatch - it’s only going to ignore those combinations. (Since an ORM query is executed in the database and not in your Python code, it has no way of generating warning messages.)