0

So I have a simple Ad model and a FilterView showing all the ads. The ads can be filtered by different tags stored in a separate model joined by a ManyToManyField.

I'm using django-filter to set up a small ModelMultipleChoiceFilter and let users select different tags to filter the Ads. This is working however it uses the tag__id. I would like it to use the tag__slug field.

Therefore I've added the attribute "to_field_name='slug'" but I get the following;

Field 'id' expected a number but got 'diner'.

The following code does work but only filters by tag__id like:

/?tags=6

and I would rather see something like this;

?tags=diner

models.py

class Ad(models.Model):
    category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
    description = RichTextField()
    tags = models.ManyToManyField('Tag')
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, null=True)

    class Meta:
        ordering = ['-title']

    def __str__(self):
        return self.title

class Tag(models.Model):
    name = models.CharField(max_length=200, help_text='Titel van de tag')
    slug = models.SlugField(max_length=200, null=True)

    def __str__(self):
        return self.name

filters.py

from django import forms
from discovery.grid.models import Ad, Tag
import django_filters

class AdFilter(django_filters.FilterSet):
    tags = django_filters.ModelMultipleChoiceFilter(
        # to_field_name='slug', 
        queryset=Tag.objects.all(),
        widget=forms.CheckboxSelectMultiple)

    class Meta:
        model = Ad
        fields = [
            'tags'
        ]

How can I achieve filtering based on the model name or slug instead of the id?

With best regards,

Kevin D.
  • 315
  • 2
  • 19

1 Answers1

0

Maybe you can try like this:

class AdFilter(django_filters.FilterSet):
    tags = CharFilter(method='my_custom_filter')

   def my_custom_filter(self, queryset, name, value):
       return queryset.filter(**{
           'tags__slug__iexact': value,
       })

    class Meta:
        model = Ad
        fields = [
            'tags'
        ]

More information can be found in documentation.

ruddra
  • 50,746
  • 7
  • 78
  • 101
  • Hmmm this does not seem to solve the problem... I still get the following; "Field 'id' expected a number but got 'diner'." – Kevin D. Feb 06 '20 at 08:36
  • The updated answer does work, however, the updated answer contains a regular input field. The point here is using the "ModelMultipleChoiceFilter" which allows the user to select different/ multiple tags to filter on. – Kevin D. Feb 06 '20 at 09:02