пользовательский запрос PostgreSQL, выполняемый приложению django - PullRequest
0 голосов
/ 15 марта 2019

У меня есть две модели с отношением один ко многим в приложении 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'

Любая идея, как это исправить

1 Ответ

0 голосов
/ 15 марта 2019

Метод Django geojson serialize ожидает набор запросов (как видно из использования здесь в документации ), а не кортеж.Из источника мы видим, что класс 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()
    ]

(dictfetchall из DjangoДокументы SQL )

Несколько моментов, которые следует отметить в приведенном выше коде:

  1. Это довольно важно: использование with для cursor такчто соединение закрыто, когда мы закончим запрашивать базу данных.Вы также можете закрыть соединение вручную, но оператор with обрабатывает его для нас.

  2. Используя функцию dictfetchall, мы преобразуем выходные данные SQL-запроса в словарь Python(готов стать JSON).Нет необходимости использовать сериализатор Django, поскольку мы используем необработанные типы данных Python вместо объектов Python или моделей Django.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...