GeoDjango distance filter with distance value stored within model - query

后端 未结 1 1150
离开以前
离开以前 2020-12-29 08:39

I have an Order model, that has an origin PointField and a range IntegerField. Furthermore, there is an UserProfile model

1条回答
  •  再見小時候
    2020-12-29 09:05

    I think you're going to have to drop some SQL in to do what you want, as the GeoDjango helpers don't have a way of you making a suitable Distance object that is simultaneously a Django F object (ie field lookup). You don't say which database you're using, but here's how you do it with PostGIS:

    Order.objects.all().extra(
        where=['ST_Distance(origin, ST_PointFromText(%s, 4326)) <= CAST(range AS double precision) / 1000'],
        params=[user.profile.geo_location.wkt]
    )
    

    Let's explain what's happening here, because it's pretty thorny. Going from the left:

    • .extra() allows you to add extra fields and restrictions into a query; here we're adding a restriction
    • ST_Distance() is the PostGIS function that the GeoDjango distance_lte operator converts into (from the Django documentation)
    • ST_PointFromText() converts from WKT syntax into a PostGIS Geometry object
    • 4326 is the default SRID for Django, but not for PostGIS so we have to specify it
    • we have to CAST your field to double precision because you're using an integer
    • then we have to divide by 1000 to convert from metres into kilometres, which I believe is what we need
    • GeoDjango Point fields have an accessor .wkt which gives their WKT representation, which we needed earlier in our ST_PointFromText() call

    Note that according to the PostGIS documentation, ST_Distance() doesn't use indexes, so you may want to investigate using ST_DWithin() instead (it's documented right after ST_Distance()).

    0 讨论(0)
提交回复
热议问题