django-rest-framework-gis icon indicating copy to clipboard operation
django-rest-framework-gis copied to clipboard

Duplicate Results for ManyToMany field with DistanceToPointFilter

Open egamonal opened this issue 9 years ago • 2 comments

A year ago a similar issue was filled for Django framework https://github.com/tomchristie/django-rest-framework/issues/1488

Model example:


class PointOfSales(models.Model):
    location = models_gis.PointField(blank=True, null=True)

class Deal(models.Model):
    promo_code = models.CharField(max_length=25, blank=True, null=True)
    points_of_sales = models.ManyToManyField(PointOfSales, related_name='deals')

I wanted to filter deals in points of sales near me:

class DealViewSet(viewsets.ReadOnlyModelViewSet):
    serializer_class = DealSerializer
    queryset = Deal.objects.all()
    filter_backends = (DistanceToPointFilter, )
    distance_filter_field = 'points_of_sales__location'
    distance_filter_convert_meters = True # by default we use srid=4326 (uses degrees), but input should be in meters

A deal in two points of sales near me will end up twice in the response.

In /rest_framework_gis/filters.py there is a filter_queryset method where I added .distinct() just like in the PR that fixed restframework https://github.com/tomchristie/django-rest-framework/pull/2535/commits/3522b69394d932c8bf8028a456b6d9b64c38b54e and I got the expected result. I didn't break any other of my tests. Might it be a fix?

    def filter_queryset(self, request, queryset, view):
        # ...
        return queryset.filter(Q(**{'%s__%s' % (filter_field, geoDjango_filter): (point, dist)})).distinct()

egamonal avatar Apr 01 '16 14:04 egamonal

In the meantime I extended the class in my filters.pymodule

from rest_framework_gis.filters import DistanceToPointFilter


class DistanceToPointFilterDistinct(DistanceToPointFilter):
    def filter_queryset(self, request, queryset, view):
        return super(DistanceToPointFilterDistinct, self).filter_queryset(request, queryset, view).distinct()

egamonal avatar Apr 01 '16 14:04 egamonal

Thanks for publishing your solution @egamonal. I'm not sure your solution can be applied as the general default case. Let's leave this issue open so if other people will encounter a similar problem we can continue the discussion.

nemesifier avatar Apr 01 '16 15:04 nemesifier