Mam model Order
, który ma origin
PointField i range
IntegerField. Ponadto istnieje model UserProfile
, który ma PointField geo_location
. Teraz mam instancję User
, user
. Chcę wybrać wszystkie Orders
, których odległość między Order.origin
i user.userprofile.geo_location
jest mniejsza niż wartość (metry) w polu modelu Order.range
.Filtr odległości GeoDjango z wartością odległości zapisaną w modelu - zapytanie
więc ponownie, uproszczone modele:
class Order(models.Model):
origin = models.PointField()
range = models.IntegerField(blank=True, default=10000)
class UserProfile(models.Model):
geo_location = models.PointField()
ja mam tej pracy (przechodząc dystans statycznie):
>>> Order.objects.filter(origin__distance_lte=(user.profile.geo_location, D(m=3000)))
My next (nieudany) Spróbuj było użyć F() wyraz użyj wartości z pola 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
Myślę, że problem polega na tym, że D() nie działa leniwie - mogę to zrozumieć. Więc starałem się po prostu wziąć wartość surowca z pola range
(Integer), które mam do pracy, ale:
>>> 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.
Więc jak mogę osiągnąć to, co usiłuję? Każda pomoc jest doceniana!
Dziękujemy za wysiłek włożenia tej odpowiedzi w całość. W końcu znalazłem rozwiązanie opisane tutaj: http://blog.adamfast.com/2011/11/radius-limited-searching-with-the-orm/ –
Dzięki za pomocną odpowiedź. Ale znalazłem ST_Distance() zwracania lon/lat stopni zamiast metrów. Oto, co zrobiłem, aby uzyskać liczniki: providers = providers.extra ( gdzie = ['ST_Distance (ST_Transform (początek, 2163), ST_Transform (ST_PointFromText (% s, 4326), 2163)) <= zakres'], params = [user.profile.geo_location.wkt] ) SRID 2163 to stożkowa projekcja stanów zjednoczonych. Zauważyłem, że rzucanie castingu jest niepotrzebne. –
Wierzę, że 'ST_Distance()' działa inaczej w zależności od tego, czy nadajesz obiektom 'Geometry' lub' Geography'. (To może lub nie uległo zmianie od czasu mojej oryginalnej odpowiedzi.) –