在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查询:
models.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'
有什么解决办法吗?
答案 0 :(得分:0)
Django geojson serialize
方法需要一个查询集(如用法here in the docs所示)而不是一个元组。从source中,我们可以看到Serializer(JSONSerializer)
类旨在“将查询集转换为GeoJSON”,并期望它可以调用._meta
的对象(即Django模型)。因此,当您将元组(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()
]
(Django SQL docs中的{dictfetchall
)
上面的代码中有两点需要注意:
这非常重要:对with
使用cursor
,以便在完成查询数据库后关闭连接。您也可以手动关闭连接,但是with
语句会为我们处理该连接。
使用dictfetchall
函数,将SQL查询的输出转换为Python字典(准备成为JSON)。由于我们使用的是原始Python数据类型而不是Python对象或Django模型,因此无需使用Django序列化程序。
答案 1 :(得分:0)
SELECT "id", "LchMatchedTradeRef", "abc" from operation_091
UNION
SELECT "id", "LchMatchedTradeRef", '' abc FROM operation_084
当您需要在Django应用中运行此查询时, 您需要像波纹管一样跟随。
empty_var = "''"
raw_query = 'SELECT "id", "LchMatchedTradeRef", "abc" FROM operation_091 UNION SELECT "id", "LchMatchedTradeRef", ' + empty_var + ' abc FROM operation_084'
cursor = connection.cursor()
cursor.execute(raw_query)