GeoDjango根据模型字段的距离进行过滤 [英] GeoDjango filter by distance from a model field

查看:111
本文介绍了GeoDjango根据模型字段的距离进行过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题与这个。但是它相当老了,感觉就像是一个很常见的情况,可能会有更好的解决方案。



我有一个类似于以下的模型:



$ _ code> class Person(models.Model):
location = models.PointField(srid = 4326)
desire_to_travel = model.IntegerField()

如果我想要在一定距离内的Person的所有实例(例如10一个点 p ,我可以这样做:

  Person.objects.filter(location__distance_lte =(p,D(mi = 10)))

但是我希望得到在特定位置的 prefer_to_travel 之间的人的所有实例。

解决方案

可以感谢地理数据库功能介绍cing in Django 1.9


允许用户访问地理数据库功能,以在Django中的
注释,聚合或过滤器中使用。


最感兴趣的是距离,可以应用在你的情况下如下:

 从django.contrib.gis.db.models.functions import距离
从django .db.models import F
Person.objects.annotate(distance = Distance('location',p)
).filter(distance__lte = F('willing_to_travel'))

请注意,这里有微妙的区别,而不是直接使用 distance_lte 这里,我们创建了一个注释,给我们一个距离列。那么我们正在使用模型查询的标准__lt比较。这翻译(大致)到

  ... WHERE ST_Distance(app_person.location,ST_GeogFromWKB(...))< 
app_person.willing_to_travel

distance_lte 它不如使用ST_Dwithin的那样有效,但是它的工作



您需要将位置转换为地理位置,因为此查询操作单位意味着学位。如果您使用地理区域,距离将以米为单位。


My question is pretty much the same as this. But its quite old and it feels like it must be a fairly common scenario that there might be a better solution to.

I have a model that is something like:

class Person(models.Model):
    location = models.PointField(srid=4326)
    willing_to_travel = models.IntegerField()

If I want all instances of Person who are within a set distance (e.g. 10 miles) of a point p, I can do it like this:

Person.objects.filter(location__distance_lte=(p, D(mi=10)))

But I would like to get all instances of Person who are within their willing_to_travel distance of a particular location.

解决方案

It is possible thanks to Geographic Database Functions introduced in Django 1.9

allow users to access geographic database functions to be used in annotations, aggregations, or filters in Django.

The one that interests us the most is Distance, it can be applied in your case as follows:

from django.contrib.gis.db.models.functions import Distance
from django.db.models import F
Person.objects.annotate(distance=Distance('location', p)
       ).filter(distance__lte=F('willing_to_travel'))

Notice that there is subtle difference here, instead of directly using distance_lte here, we have created an annotation that yields us a distance column. Then we are using the standard __lt comparision from the model queryset on it. This translates (roughly) in to

   ... WHERE ST_Distance(app_person.location, ST_GeogFromWKB(...)) < 
       app_person.willing_to_travel

Which is similar to the one produced by distance_lte It's not as efficient as one that uses ST_Dwithin but it does the job

you would need to convert location to geography because this query operates on 'units of the field' which means degrees. If you use geography fields the distance will be in meters.

这篇关于GeoDjango根据模型字段的距离进行过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆