#django #django-models #django-views #django-queryset
#django #django-модели #django-просмотры #django-queryset
Вопрос:
Я сохранил координаты пользователя в User
модели. Модель Post имеет latitude
longitude
и radius
поле. Только пользователи в этом районе (Post) смогут увидеть это сообщение. Я не знаю, как использовать filter()
здесь, поэтому я использовал следующий подход:
post=Posts.objects.all()
for a in post:
distance= geopy.distance.geodesic((lat1,lng1), (a.latitude, a.longitude)).km
print(distance)
if distance < a.radius:
p.append(a)
else:
continue
Здесь lat1
и lng1
указаны координаты текущего User
. Предложите, есть ли лучший способ, поскольку это кажется очень неэффективным.
Комментарии:
1. Вы можете работать с запросами GeoDjango , если используете базу данных PostGIS или SpatiaLite.
2. @WillemVanOnsem я могу, но это много хлопот только для одного простого запроса, который я хочу сделать. Я уверен, что должен быть простой способ сделать это.
3. ну, внутренне часто такие базы данных работают с пространственным k-d деревом для индексации данных. Это заставляет поиск часто принимать O (log n) вместо линейного подхода.
4. @WillemVanOnsem PostGIS это тогда. Спасибо. Я оставлю его открытым на случай, если у кого-то есть уникальный подход к этому.
Ответ №1:
В зависимости от ваших требований вы можете использовать квадрат вместо круга. Предварительно вычислите границы x-max, x-min, y-max и y-min для вашего квадрата, а затем выполните простой User.filter(lat__gt=lat_min, user.lng__gt=lng_min, user.lat__lt=lat_max ...
поиск в базе данных.
В прошлом проекте я использовал это:
def get_latlng_bounderies(lat, lng, distance):
"""
Return min/max lat/lng values for a distance around a latlng.
:lat:, :lng: the center of the area.
:distance: in km, the "radius" around the center point.
:returns: Two corner points of a square that countains the circle,
lat_min, lng_min, lat_max, lng_max.
"""
gc = great_circle(kilometers=distance)
p0 = gc.destination((lat, lng), 0)
p90 = gc.destination((lat, lng), 90)
p180 = gc.destination((lat, lng), 180)
p270 = gc.destination((lat, lng), 270)
ret = p180[0], p270[1], p0[0], p90[1]
return ret
Это не круг, поэтому он не точен вокруг «углов» квадрата, но намного быстрее, потому что это простое сравнение с плавающей точкой в базе данных.
Комментарии:
1. Это очень умный способ обойти эту проблему. Я проанализирую свои требования и, возможно, воспользуюсь этим. Спасибо за такой отличный ответ.