问题
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.
回答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).
来源:https://stackoverflow.com/questions/25047964/geodjango-geoqueryset-distance-results-in-st-distance-output-only-available-o