Search code examples
djangodjango-filter

Django-filter filtering by reverse foreignkey


I have a 3 models: Product, Action, ActionProduct.

class Product (models.Model):
     p = models.CharField()

class Action(models.Model):
     a = ... 
     <a lot more fields>
    
class ActionProduct(models.Model):
    product = ForeignKey(ProductList)
    action = ForeignKey(Action)

My goal is to be able to filter Action model by product.

It works great with other fields and Foreign keys, like category, author, etc:

category = django_filters.ModelMultipleChoiceFilter(
    queryset=CategorySocial.objects.all() 
)

But how do I filter by reverse foreign key?

Challenge comes when using django-filters and want to filter Action model by product. I tried to rearrange by filtering ActionProduct model. It almost works. But product model was added recently, and not all actions has Product chosen, so actions without product is lost.

Could you guide me to some direction?


Solution

  • A ManyToManyField would simply implicitly make a model similar to the ActionProduct model you have made. Since you have already made this model simply specify it as the through model [Django docs] for the ManyToManyField. This way you can make queries easier and you can then filter easily:

    class Action(models.Model):
         a = ... 
         products = models.ManyToManyField(
             Product,
             through='ActionProduct',
             related_name='actions'
         )
         <a lot more fields>
    

    Now run python manage.py makemigrations and python manage.py migrate so that your migration files reflect this.

    Now in your filterset you can simply add products as a ModelMultipleChoiceFilter as it is a field on your model:

    products = django_filters.ModelMultipleChoiceFilter(
        queryset=Product.objects.all() 
    )
    

    Or simply add it to fields attribute in Meta of the filterset:

    class SomeFilter(django_filters.FilterSet):
        class Meta:
            model = Action
            fields = ['products', ...]