carltongibson / django-filter

A generic system for filtering Django QuerySets based on user selections
https://django-filter.readthedocs.io/en/main/
Other
4.41k stars 766 forks source link

The filter result contains duplicate instance when filter by many_to_many field #1579

Closed peijianbo closed 1 year ago

peijianbo commented 1 year ago

Exmple:

model: class Tag(models.Model): key = models.CharField(max_length=64, verbosename=('键')) value = models.CharField(max_length=64, verbosename=('值'))

class Resource(models.Model): name = models.CharField(max_length=64, verbosename=('名称')) tags = models.ManyToManyField('tag.Tag', related_name='resources', verbosename=('标签'))

view: class ResourceViewSet(ModelViewSet): filter_fields = ('tagskey', 'tagsvalue') queryset = Resource.objects.all() serializer_class = ResourceSerializer ...

then create some tags and resources instances and make relation: tag1 = Tag.objects.create(key='env', value='prod') tag2 = Tag.objects.create(key='env', value='dev') resource1 = Resource.objects.create(name='test') resource.tags.add(*[tag1, tag2])

when i get 127.0.0.1/resource/resources/?tags__key=env there will return tow obj: [ {'id': 1, 'name': 'test'}, {'id': 1, 'name': 'test'} ]

version: Django(3.2) + djangorestframework(3.12.4) + django-filter(21.1)

carltongibson commented 1 year ago

You need to use distinct. See the docs: https://django-filter.readthedocs.io/en/latest/ref/filters.html?highlight=Distinct#distinct

peijianbo commented 1 year ago

@carltongibson i think is not a friendly design that the distinct default value is True. if that i have to write the filterset if any model has m_2_m filed. if the default value is True, I only set filter_fields = ('tagskey', 'tagsvalue') in viewset.