Reputation: 89
I have an Event model, serializer, viewset, and a Tag model, serializer, viewset. I want filter Events by tags_name. But it's only possible to filter it by tag_id
In tag serializer I've set lookup_field
in TagSerializer. Option when I 'filter_field = (tags__name)' is not appropriate, because last GET
parameter change previous
class Event(models.Model):
tags = models.ManyToManyField('Tag')
...
class Meta:
ordering = ['name']
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(unique=True, max_length=50)
def __str__(self):
return self.name
def __unicode__(self):
return '%s'% (self.name)
class EventSerializer(serializers.ModelSerializer):
from accounts.api.serializers import ShortUserSerializer
tags = serializers.SlugRelatedField(
many=True,
queryset=Tag.objects.all(),
slug_field='name'
)
members_count = serializers.SerializerMethodField()
author = ShortUserSerializer()
max_members = serializers.IntegerField(required=False, default=-1)
class Meta:
model = Event
fields = ['id', 'name', 'description', 'time_begins', 'author', 'members_count', 'max_members', 'tags',
'avatar', 'date_expire', 'city', 'country', 'geo']
...
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'
lookup_field = 'name'
extra_kwargs = {
'url': {'lookup_field': 'name'}
}
...
class EventViewSet(viewsets.ModelViewSet):
queryset = Event.objects.all()
serializer_class = EventSerializer
http_method_names = ['get', 'patch']
filter_backends = (filters.SearchFilter, DjangoFilterBackend,)
search_fields = ('name', 'author__username', )
filter_fields = ('tags')
I receive result with this:
`localhost:8000/events/?tags=1&tags=2`
And it actually works
But I need:
`localhost:8000/events/?tags=#fun&tags=#movie`
Upvotes: 1
Views: 1957
Reputation: 315
What about if you try to use like this filterset_fields = ['tags__name', ]
and then access by ?tags__name=name
Upvotes: 4
Reputation: 6296
This case is not taken care of by the default filtersets generated from filter_fields
. For foreign relationships it uses the idea.
Therefore, you have to define your custom filterset like this
class EventFilter(filters.FilterSet):
tags = filters.CharFilter(field_name="tags__name", method='filter_tags')
class Meta:
model = Event
fields = ['tags']
def filter_tags(self, queryset, name, tags):
return queryset.filter(tags__name__contains=tags.split(','))
Then you need to remove the filter_fields
and add this as your filter_class
in EventViewSet
class EventViewSet(viewsets.ModelViewSet):
queryset = Event.objects.all()
serializer_class = EventSerializer
http_method_names = ['get', 'patch']
filter_backends = (filters.SearchFilter, DjangoFilterBackend,)
search_fields = ('name', 'author__username', )
filter_class = EventFilter
Upvotes: 1