Saltar al contenido

Consultas SQL en la capa de base de datos PostGIS usando Python y QGIS

Queremos enseñarte la mejor respuesta que hemos encontrado on line. Nosotros esperamos que te sea de utilidad y si puedes comentarnos algo que nos pueda ayudar a perfeccionar nuestra información puedes hacerlo..

Solución:

Agregar una tabla PostGIS a un mapa QGIS

En un complemento de QGIS, usaría QgsDataSourceURI de la API de pyqgis. Aquí hay un fragmento de un proyecto en el que trabajé.

La conexión a la base de datos está envuelta en una función. Todo lo que necesitas es db_params. La contraseña solo está codificada en base64; Ya que el pw no es un gran secreto y los usuarios donde trabajo no son hackers.

def get_dbparams(self):
    # Get db connections params #
    DB = 'somedb'
    PORT = 5432
    HOST = '11.22.333.44'

    user = self.get_userrole()

    if user == GrukosUser.READER:
        db_params = 
            'dbname': DB,
            'user': 'grukosreader',
            'host': HOST,
            'password': base64.b64decode('SDFADSASDFADF'),
            'port': PORT
        
        return db_params
    elif user == GrukosUser.WRITER:
        db_params = 
            'dbname': DB,
            'user': 'grukoswriter',
            'host': HOST,
            'password': base64.b64decode('SDFGSGSDFGSDFGSDF'),
            'port': PORT
        
        return db_params
    else:
        return None

Obtenga los parámetros:

    db = MyDb()
    params = db.get_dbparams()

Establecer la fuente de datos:

uri = QgsDataSourceURI()
uri.setConnection(params['host'], str(params['port']), params['dbname'], params['user'], params['password'])

Si usa un filtro en la mesa sin geometría:

 uri.setDataSource("myschema", "mytablename", None, "mycolumn=".format(myvalue))

Si usa un filtro en una mesa con una geometría:

uri.setDataSource("myschema", "mytablename", "mygeom", "mycolumn=".format(myvalue))

Si no hay filtro ni geometría:

uri.setDataSource("myschema", "mytablename", None)

Si no hay filtro ni geometría:

uri.setDataSource("myschema", "mytablename", "geom")

Si usa una vista espacial. Debe tener una columna única. Aquí llamado id:

uri.setDataSource("myschema", "mytablename", "geom", aKeyColumn='id')
uri.setKeyColumn('id')

Luego:

vlayer = QgsVectorLayer(uri.uri(), "mylayername", "postgres")

Verificar validez:

if not vlayer.isValid():
   ...

Agregar al mapa:

QgsMapLayerRegistry.instance().addMapLayer(vlayer, True)

Ningún mapa solo necesita obtener algunos datos de Postgres

Yo uso psycopg2 como:

def get_projectid(self, gkoid):
    """ Use a PostgreSQL function to translate gkoid to projectid """
    sql = 'SELECT myschema.mypgfunction();'.format(gkoid)
    cur = self.execute_sql(sql)
    rows_tuple = cur.fetchone()
    projectid = rows_tuple[0]

    return projekcid, sql

def execute_sql(self, sql, dict_cursor=True, print_sql=False):

    """ Execute a SQL query
    :param sql: SQL to be executed
    :param dict_cursor: Flag indicating if cursor is a dict or not. Use false for scalar queries
    :param print_sql: Flag indicating if sql is to be printet
    :return: returns a cursor
    """

    if print_sql: print sql
    conn = psycopg2.connect(**self.get_dbparams())

    if dict_cursor:
        cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
    else:
        cur = conn.cursor()

    try:
        cur.execute(sql)
        return cur
    except psycopg2.DatabaseError, e:
        print 'Some error '.format(e)
        sys.exit(1)
    finally:
        pass
        #TODO
        #if conn:
        #    conn.close()

Inicio sesión

En algunos casos, un error en SQL bloqueará QGIS de una vez. Una forma de depuración es conectarse al QgsMessageLog. Lo envuelvo en una función como esta:

def enable_qgis_log(filename = 'D:gqis.log', haltApp = False, haltMsg = 'stop'):
    """ Very useful when QGIS crashes on PGSQL error
    :param filename: Filename and path for log file
    :param haltApp: Halts the application with a modal dialog
    :param haltMsg: Message to user when showing model stopping dialog
    :rtype: None
    """
    def write_log_message(message, tag, level):
        with open(filename, 'a') as logfile:
            logfile.write('tag(level): message'.format(tag=tag, level=level, message=message))

    QgsMessageLog.instance().messageReceived.connect(write_log_message)

    if haltApp:
        QtGui.QMessageBox.information(None, GrukosAux.GRUKOS, "".format(haltMsg.encode('cp1252')), QtGui.QMessageBox.Ok) 

Si conn es su conexión de base de datos desde su código anterior, dispara su declaración sql de la siguiente manera:

c = conn.cursor()
c.execute('SELECT * FROM mytesttable')
c.fetchall()

Dónde fetchall() devuelve una lista de tuplas que contienen los valores de columna de su SELECT (implica que conoce su orden cuando SELECTEn g *).

Tenga en cuenta que psycopg2 como un cliente de base de datos no confirma automáticamente los cambios de la base de datos cuando usa declaraciones como INSERT o UPDATE. En los últimos casos, tienes que terminar implícitamente tu declaración con

c.execute('COMMIT;')

Finalizando este artículo puedes encontrar las reseñas de otros administradores, tú además tienes el poder dejar el tuyo si lo crees conveniente.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *