djangodjango-modelsdjango-querysetdjango-q

Is there a way to use modulo to check value in django Q object?


I have a script which does some filtering operations on a database in a very dynamic manner. What I need is to create a very specific condition in certain cases which requires me to check if a field is divisble by 500. A relevant snippet is below:

            title_filter_weekly = Q(
                option__title__startswith=str(index),
                option__title__endswith=str(expiry_date.strftime("%d"))
                + str(expiry_date.strftime("%b").upper())
                + str(expiry_date.strftime("%y"))
                + option_entry_type,
            )
            title_filter_monthly = Q(
                option__title__startswith=str(index),
                option__title__endswith=str(expiry_date.strftime("%b").upper()) + str(expiry_date.strftime("%y")) + option_entry_type,
                option__is_monthly=True,
            )

            # Check if "leg_round_value" is in position_info and True
            round_value_condition = (
                "leg_round_value" in position_info and position_info["leg_round_value"]
            )

            # Apply the additional condition for divisibility by 500
            if round_value_condition:
                title_filter_weekly &= Q(option__strike_price)
                title_filter_monthly &= Q(option__strike_price)

The last two lines are incomplete, what I basically want is to add in the condition that option__strike_price is divisible by 500.

I can try to possibly do the intial filtering, and then further filter via loop, but I want minimise queries as much as possible and it seems like there may be a better way.


Solution

  • It's possible to achieve that using Mod database function

     SomeModel.objects.annotate(mod_500=Mod('value_field', 500)).filter(mod_500=0)
    

    For Django version greater or equal to 3.2 you can also use alias for improved performance (if you are not using result of modulo anywhere)

    SomeModel.objects.alias(mod_500=Mod('value_field', 500)).filter(mod_500=0)
    

    Both snippets check if value of value_field and 500 are equal to 0 which means they are divisible by 500 without remainder