我试图从用户当前位置获取附近的牙医列表。
用户当前位置(纬度和经度)通过查询参数发送。
牙医的位置保存在名为 location 的模型中,其中牙医的 id 是外键和唯一标识符。 我在 LocationSerializer 中使用了 drf_extra_fields.geo_fields 中的 PointField 字段
我正在使用 python 3.10 和 Django 3.2.8
型号
class Location(models.Model):
id = models.OneToOneField(Dentist, on_delete=models.CASCADE, primary_key=True)
location = models.PointField(srid=4326)
序列化器
from drf_extra_fields.geo_fields import PointField
class LocationSerializer(serializers.ModelSerializer):
location = PointField()
class Meta:
model = Location
fields = ['id', 'location']
查看
class NearByDentistView(APIView):
def get(self,request):
longitude = float(self.request.query_params.get('longitude'))
latitude = float(self.request.query_params.get('latitude'))
user_location = Point(latitude,longitude,srid=4326)
queryset = Location.objects.filter(location__distance_lte=(user_location, D(km=100)))
serializer = LocationSerializer(queryset,many=True)
return Response(serializer.data)
回复
Internal Server Error: /api/v1/user/dentist/nearby/
Traceback (most recent call last):
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\backends\utils.py", line 82, in _execute
return self.cursor.execute(sql)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\backends\sqlite3\base.py", line 421, in execute
return Database.Cursor.execute(self, query)
sqlite3.OperationalError: no such function: lwgeom_version
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\asgiref\sync.py", line 482, in thread_handler
raise exc_info[1]
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\core\handlers\exception.py", line 38, in inner
response = await get_response(request)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\core\handlers\base.py", line 233, in _get_response_async
response = await wrapped_callback(request, *callback_args, **callback_kwargs)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\asgiref\sync.py", line 444, in __call__
ret = await asyncio.wait_for(future, timeout=None)
File "C:\Users\amanu\AppData\Local\Programs\Python\Python310\lib\asyncio\tasks.py", line 408, in wait_for
return await fut
File "C:\Users\amanu\AppData\Local\Programs\Python\Python310\lib\concurrent\futures\thread.py", line 52, in run
result = self.fn(*self.args, **self.kwargs)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\asgiref\sync.py", line 486, in thread_handler
return func(*args, **kwargs)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\views\generic\base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
raise exc
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "D:\CODES\Django\SMILE_BACKEND\users\views.py", line 470, in get
return Response(serializer.data)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\rest_framework\serializers.py", line 745, in data
ret = super().data
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\rest_framework\serializers.py", line 246, in data
self._data = self.to_representation(self.instance)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\rest_framework\serializers.py", line 663, in to_representation
return [
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\models\query.py", line 280, in __iter__
self._fetch_all()
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\models\query.py", line 1324, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\models\query.py", line 51, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1162, in execute_sql
sql, params = self.as_sql()
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\models\sql\compiler.py", line 528, in as_sql
where, w_params = self.compile(self.where) if self.where is not None else ("", [])
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\models\sql\compiler.py", line 445, in compile
sql, params = node.as_sql(self, self.connection)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\models\sql\where.py", line 81, in as_sql
sql, params = compiler.compile(child)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\models\sql\compiler.py", line 445, in compile
sql, params = node.as_sql(self, self.connection)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\contrib\gis\db\models\lookups.py", line 330, in as_sql
sql, params = compiler.compile(distance_expr.resolve_expression(compiler.query))
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\models\sql\compiler.py", line 443, in compile
sql, params = vendor_impl(self, self.connection)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\contrib\gis\db\models\functions.py", line 297, in as_sqlite
return super().as_sql(compiler, connection, **extra_context)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\contrib\gis\db\models\functions.py", line 52, in as_sql
function = connection.ops.spatial_function_name(self.name)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\contrib\gis\db\backends\base\operations.py", line 115, in spatial_function_name
if func_name in self.unsupported_functions:
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\utils\functional.py", line 48, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\contrib\gis\db\backends\spatialite\operations.py", line 84, in unsupported_functions
if not self.lwgeom_version():
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\contrib\gis\db\backends\spatialite\operations.py", line 168, in lwgeom_version
return self._get_spatialite_func('lwgeom_version()')
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\contrib\gis\db\backends\spatialite\operations.py", line 152, in _get_spatialite_func
cursor.execute('SELECT %s' % func)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\backends\utils.py", line 98, in execute
return super().execute(sql, params)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\backends\utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\backends\utils.py", line 79, in _execute
with self.db.wrap_database_errors:
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\backends\utils.py", line 82, in _execute
return self.cursor.execute(sql)
File "d:\CODES\Django\SMILE_BACKEND\venv\lib\site-packages\django\db\backends\sqlite3\base.py", line 421, in execute
return Database.Cursor.execute(self, query)
django.db.utils.OperationalError: no such function: lwgeom_version
←[35;1mHTTP GET /api/v1/user/dentist/nearby/?latitude=69.764447962023&longitude=69.165280763008 500 [6.63, 127.0.0.1:13111]←[0m
您使用什么数据库? 错误消息指出缺少函数lwgeom_version。
如果您使用的是 Django 框架使用的默认数据库 SQlite,则需要安装 SpatiaLite。 SpatiaLite 通过合并 LWGEOM(轻量级几何库)添加了对 SQlite 的空间支持,PostGIS 也使用该库来添加对 Postgres 数据库的支持。
对于空间查找,您正在查询以查找球面/曲面(地球)上的点(使用 srid=4326 或 WGS84 标准)的最短距离计算。这需要使用地理坐标系来计算几何图形之间的距离,而 SpatiaLite 似乎没有能力做到这一点。相反,您可以使用 Postgres(即 PostGis)使用
GeometryField.geography
等方法来添加此容量,并具有更好的性能。
您可以参考完整的 GeoDjango 模型 API 这里。
与 SpatiaLight 版本相比,Django 版本太旧时可能会出现此问题。 SpatiaLight 5.0 不支持 Django 3.2。尝试将 Django 更新为例如v4