python - 自定义 PostgreSQL 查询执行到 django 应用程序
问题描述
我在 django 应用程序中使用 postgres/postgis 数据库的应用程序有两个具有一对多关系的模型。我在数据库和 pgadmin 面板中创建了一个不容易的查询并且工作正常。
这里是查询:
select string_agg(distinct app_work.id::text, ', ') AS code_work,string_agg(distinct app_work.stage, ', ')
AS stage,string_agg(distinct app_work.dfield_work, ', ') AS dfield,app_point.geom
from app_point, app_work where app_point.id=app_work.point_field_id GROUP BY app_point.id;
现在我想在我的 django 应用程序中使用这个查询(我需要这个查询的结果)来创建一个 geojson 或 json 导出。我不确定如何使用 django 方法对象和查询(如point.objects.all()
)转换此查询我尝试使用这样的自定义 postgres 查询:
模型.py
class point(models.Model):
geom = models.MultiPointField(srid=4326)
objects = models.GeoManager()
def __unicode__(self):
return str(self.id)
class meta:
verbose_name_plural="point_info"
class work(models.Model):
dfield_work = models.CharField(max_length=100,blank=True, null=True)
stage = models.CharField(max_length=100,blank=True, null=True)
field1 = models.CharField(max_length=100,blank=True, null=True)
field2 = models.CharField(max_length=100,blank=True, null=True)
point_field= models.ForeignKey('point', blank=True, null=True)
def __unicode__(self):
return str(self.id)
vews.py
from django.db import connection
def points(request):
cursor = connection.cursor()
cursor.execute("""seselect string_agg(distinct app_work.id::text, ', ') AS code_work,string_agg(distinct app_work.stage, ', ')
AS stage,string_agg(distinct app_work.dfield_work, ', ') AS dfield,app_point.geom
from app_point, app_work where app_point.id=app_work.point_field_id GROUP BY app_point.id from log_point, log_work where log_point.id=log_work.point_field_id GROUP BY log_point.id""")
row = cursor.fetchall()
print row
data = serialize('geojson', row)
return HttpResponse(data,content_type='json')
在打印行中,我采用了正确的列表结果
但不工作,我有这个错误:
'tuple' object has no attribute '_meta'
知道如何解决吗?
解决方案
Django geojson方法需要一个查询集(从docs 中的serialize
用法可以看出)而不是一个元组。从源代码中,我们可以看到该类旨在“将查询集转换为 GeoJSON”并期望它可以调用的对象(即 Django 模型)。因此,当您将元组(的输出)传递给您时,您会得到错误。Serializer(JSONSerializer)
._meta
cursor.fetchall()
serialize
'tuple' object has no attribute '_meta'
由于您使用的是原始 SQL 查询,因此实际上不需要使用 geojson 序列化程序,因为它旨在将 Python 对象转换为 JSON。您可以改为将 SQL 查询的输出转换为 JSON 并将其作为响应发送。
这是一个例子:
import json
from django.db import connection
from django.http import HttpResponse
query_text = """
SELECT
string_agg(distinct app_work.id::text, ', ') AS code_work,
string_agg(distinct app_work.stage, ', ') AS stage,
string_agg(distinct app_work.dfield_work, ', ') AS dfield,
app_point.geom
FROM
app_point, app_work
WHERE
app_point.id = app_work.point_field_id
GROUP BY
app_point.id;
"""
def points(request):
with connection.cursor() as cursor:
cursor.execute(query_text)
data = dictfetchall(cursor)
stringified_data = json.dumps(data)
return HttpResponse(stringified_data, content_type="application/json")
def dictfetchall(cursor):
"Return all rows from a cursor as a dict"
columns = [col[0] for col in cursor.description]
return [
dict(zip(columns, row))
for row in cursor.fetchall()
]
(dictfetchall
来自Django SQL 文档)
在上面的代码中有几点需要注意:
这是相当重要的:使用
with
forcursor
以便在我们完成对数据库的查询时关闭连接。您也可以手动关闭连接,但with
语句会为我们处理它。使用该
dictfetchall
函数,我们将 SQL 查询的输出转换为 Python 字典(准备成为 JSON)。不需要使用 Django 序列化程序,因为我们使用的是原始 Python 数据类型而不是 Python 对象或 Django 模型。
推荐阅读
- functional-programming - 在 Lisp 中的 mapcon 上应用附加
- tsql - 编写递归 CTE
- macos - 禁用 Safari 的暗模式,独立于操作系统设置
- sql - 在 UPDATE 语句中使用 LAG 函数
- r - 如何给命令多个数字并输出多个对象R
- javascript - 如何更新一串mongodb文档的一部分?
- c# - 向 ASP.NET Core 模型添加列表参数
- c# - 在 wpf 中添加第二个窗口
- python - ReactJs 应用程序和 Python 服务器中的 UTC 时差
- python - 在 vs code python 调试控制台中运行循环/多行