Tôi có một mô hình Order
, có origin
PointField và range
IntegerField. Hơn nữa, có một mô hình UserProfile
, trong đó có một điểm số geo_location
. Bây giờ, tôi có một phiên bản User
, user
. Tôi muốn chọn tất cả Orders
, có khoảng cách giữa Order.origin
và user.userprofile.geo_location
ít hơn giá trị (mét) trong trường mô hình Order.range
.Bộ lọc khoảng cách GeoDjango với giá trị khoảng cách được lưu trong mô hình - truy vấn
Vì vậy, một lần nữa, các mô hình đơn giản:
class Order(models.Model):
origin = models.PointField()
range = models.IntegerField(blank=True, default=10000)
class UserProfile(models.Model):
geo_location = models.PointField()
Tôi đã có làm việc này (đi qua các khoảng cách tĩnh):
>>> Order.objects.filter(origin__distance_lte=(user.profile.geo_location, D(m=3000)))
My tiếp theo (không thành công) thử là sử dụng một biểu thức F() để sử dụng giá trị từ trường Order.range
:
>>> Order.objects.filter(origin__distance_lte=(user.profile.geo_location, D(m=F('range'))))
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/contrib/gis/measure.py", line 165, in __init__
self.m, self._default_unit = self.default_units(kwargs)
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/contrib/gis/measure.py", line 49, in default_units
if not isinstance(value, float): value = float(value)
TypeError: float() argument must be a string or a number
Tôi nghĩ rằng vấn đề là D() không chạy lười biếng - tôi có thể hiểu điều đó. Vì vậy, tôi đã cố gắng để chỉ lấy giá trị nguyên từ range
lĩnh vực (số nguyên) mà tôi cho là để làm việc, nhưng:
>>> Order.objects.filter(origin__distance_lte=(user.profile.geo_location, F('range')))
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/db/models/query.py", line 69, in __repr__
data = list(self[:REPR_OUTPUT_SIZE + 1])
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/db/models/query.py", line 84, in __len__
self._result_cache.extend(self._iter)
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/db/models/query.py", line 273, in iterator
for row in compiler.results_iter():
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 680, in results_iter
for rows in self.execute_sql(MULTI):
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 725, in execute_sql
sql, params = self.as_sql()
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 68, in as_sql
where, w_params = self.query.where.as_sql(qn=qn, connection=self.connection)
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/db/models/sql/where.py", line 92, in as_sql
sql, params = child.as_sql(qn=qn, connection=connection)
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/db/models/sql/where.py", line 95, in as_sql
sql, params = self.make_atom(child, qn, connection)
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/contrib/gis/db/models/sql/where.py", line 47, in make_atom
spatial_sql = connection.ops.spatial_lookup_sql(data, lookup_type, params_or_value, lvalue.field, qn)
File "/Users/danger/devel/.virtualenvs/proj/lib/python2.7/site-packages/django/contrib/gis/db/backends/postgis/operations.py", line 531, in spatial_lookup_sql
raise ValueError('Argument type should be %s, got %s instead.' % (arg_type, type(value[1])))
ValueError: Argument type should be (<class 'decimal.Decimal'>, <class 'django.contrib.gis.measure.Distance'>, <type 'float'>, <type 'int'>, <type 'long'>), got <class 'django.db.models.expressions.F'> instead.
Vậy làm thế nào tôi có thể thực hiện những gì tôi đang cố gắng? Bất kỳ trợ giúp được đánh giá cao!
Cảm ơn bạn đã nỗ lực đưa câu trả lời này cùng nhau. Cuối cùng tôi đã kết thúc với một giải pháp được mô tả ở đây: http://blog.adamfast.com/2011/11/radius-limited-searching-with-the-orm/ –
Cảm ơn câu trả lời hữu ích. Nhưng, tôi đã tìm thấy ST_Distance() để trở về độ cô đơn/lat thay vì mét. Dưới đây là những gì tôi đã làm để có được mét: nhà cung cấp = providers.extra ( trong đó = ['ST_Distance (ST_Transform (origin, 2163), ST_Transform (ST_PointFromText (% s, 4326), 2163)) <= range'], params = [user.profile.geo_location.wkt] ) SRID 2163 là phép chiếu hình nón của các quốc gia thống nhất. Tôi tìm thấy đúc để tăng gấp đôi không cần thiết quá. –
Tôi tin rằng 'ST_Distance()' hoạt động khác nhau tùy thuộc vào việc bạn cung cấp cho nó các đối tượng 'Geometry' hay' Geography'. (Điều này có thể hoặc có thể không thay đổi kể từ câu trả lời ban đầu của tôi.) –