2

From the docs and other questions, sorting a GeoQuerySet by distance should be straightforward, but I'm having trouble getting it work. Here is an example to demonstrate the situation of the problem:

Lets say I got two models in two different apps. One model in appA and another in appB as defined below:

# appA/models.py
class Store(models.Model):
        title = models.CharField()


# appB/models.py
from appA.models import Store

class StoreLocation(models.Model):
    store = models.ForiegnKey(Store)
    location = models.PointField()

Now, I want to get all the Stores that are within two miles of a user's location (user_location) like so:

stores = Store.objects.filter(storelocation__location__dwithin(user_location, D(mi=2))

So far so good. Everything up to here works. The problem starts when I want to now sort the Stores by their distance to user_location:

stores = Store.objects.filter(storelocation__location__dwithin(user_location, D(mi=2))\
         .distance(user_loc, field_name='storelocation__location')\
         .order_by('distance')

This results into TypeError: ST_Distance output only available on GeometryFields.

The location field of the StoreLocation model is a PointField which is a GeometryField. So the issue is with the reverse relationship lookup done by field_name='storelocation__location'.

There is a Django support ticket (https://code.djangoproject.com/ticket/22352) requesting support for reverse relationship lookups in field_name for OneToOne relationships, but my models have a OneToMany relationship through a ForeignKey so I'm not sure if the support ticket applies to this problem.

Judging from the Django documentation (https://docs.djangoproject.com/en/1.6/ref/contrib/gis/geoquerysets/#geoqueryset-methods) it doesn't seem like I'm misusing anything here.

Are reverse relationship lookups allowed with the field_name argument of GeoQuerySet methods? Or am I just doing something wrong?

The solution provided in this question (GeoDjango distance query for a ForeignKey Relationship) didn't help either.

Community
  • 1
  • 1
Amir Rustamzadeh
  • 4,302
  • 7
  • 35
  • 43

1 Answers1

1

I suspect you are getting bit by the same issue mentioned in Django support ticket 22352, since related fields (whether one-to-one or one-to-many) share much of the same code.

You can still efficiently get nearby stores ordered by distance:

locations = StoreLocation.objects.filter(location__dwithin=(user_location, D(mi=2)))
locations = locations.distance(user_location).order_by('distance')
stores = [sl.store for sl in locations.select_related('store')]

However, this loses the benefits of having stores be a queryset (which could be further filtered, sliced, etc).

tcarobruce
  • 3,773
  • 21
  • 33
  • 1
    I was afraid this was going to be the answer. Thank you, now I know it wasn't just something I was doing wrong. Hopefully the proposed patch for the ticket will get into a release. Also, for the sake of completeness, if someone wants to to get (inefficiently) QuerySet out this list they can refer to this trick: http://stackoverflow.com/a/4790371/394988 – Amir Rustamzadeh Jul 31 '14 at 00:23