Describiendo Bases de Datos con MetaData – SQLAlchemy

En este artículo vamos a ver cómo describir Bases de Datos con MetaData usando SQLAlchemy en Python.

Los metadatos de la base de datos describen la estructura de la base de datos en términos de estructuras de datos de Python. La base de datos generalmente consta de tablas y columnas. Los metadatos de la base de datos nos sirven para generar consultas SQL y mapeo relacional de objetos. Nos ayuda a generar un Esquema. Los objetos más fundamentales de los metadatos de la base de datos son los metadatos, la tabla y la columna.

Describiendo bases de datos con metadatos: SQLAlchemy Core 

Configuración de metadatos con objetos de tabla:

Las consultas en una base de datos relacional generalmente se crean en una tabla de una base de datos. Estas tablas se representan como objetos de tabla en Python SQLAlchemy con el nombre de tabla. Los metadatos son un objeto que consta de objetos de tabla codificados con sus nombres de string. La sintaxis para crear un objeto MetaData es la siguiente:

from sqlalchemy import MetaData
metadata_obj=MetaData()

Un solo objeto MetaData es suficiente para una aplicación completa. Una vez que se crea el objeto MetaData, podemos declarar objetos Table. Veamos un ejemplo de creación de una tabla para una cuenta de estudiante que consta de columnas: nombre, edad y grado y también agregamos una identificación como clave principal.

Ahora convertimos la tabla anterior en un Esquema usando el objeto MetaData.

Python3

from sqlalchemy import MetaData
from sqlalchemy import Integer, String, Column, Table
 
metadata_object=MetaData()
 
student_table = Table(
     "student_account",
     metadata_object,
     Column('id', Integer, primary_key=True),
     Column('name', String(30)),
     Column('age',Integer),
     Column('grade', String(80))
)

En el código anterior, una tabla representa una tabla de base de datos que se asigna a sí misma al objeto MetaData.

Una Columna representa una Columna de una Tabla que se asigna a sí misma al objeto Tabla. La columna generalmente contiene un nombre de string y un objeto de tipo como Integer, String, etc.

Crear una tabla con diferentes tipos de datos

Python3

from sqlalchemy import create_engine
from sqlalchemy import DateTime, Numeric, Enum
 
item_detail = Table(
    "items",
    metadata_object,
    Column("key", String(50), primary_key=True),
    Column("timestamp", DateTime),
    Column("price", Numeric(100, 2)),
    Column("type", Enum("dry", "wet")),
)
 
# creating an engine object
engine = create_engine("sqlite+pysqlite:///:memory:",
                       echo=True, future=True)
 
# emitting DDL
metadata_object.create_all(engine)

Acceso a tablas y columnas

Las columnas de una tabla generalmente se almacenan en una array asociativa, es decir, Table.c , y se puede acceder a ellas usando «c», como se muestra en los siguientes ejemplos.

Obteniendo el nombre de la tabla:

Python3

student_table.name

Producción:

'student_account'

Accediendo a columnas usando el operador c:

Python3

student_table.c.name

Producción:

Columna(‘nombre’, String(longitud=30), tabla=<cuenta_del_estudiante>)

Acceso al nombre de una columna (nombre):

Python3

student_table.c.name.name

Producción:

name

Tipo de acceso de una columna:

Python3

student_table.c.name.type

Producción:

String(length=30)

Obtener la clave principal de una tabla:

Python3

student_table.primary_key

Producción:

PrimaryKeyConstraint(Column(‘id’, Integer(), table=<student_account>, primary_key=True, anulable=False))

Acceder a tablas y claves usando el objeto MetaData

El objeto de metadatos se puede utilizar para acceder a todas las tablas almacenadas en el objeto de metadatos, como se muestra en los siguientes ejemplos:

Acceso a tablas en metadatos:

Python3

metadata_object.tables

Producción:

FacadeDict({‘cuenta_estudiante’: Table(‘cuenta_estudiante’, MetaData(), Column(‘id’, Integer(), table=<cuenta_estudiante>, clave_principal=Verdadero, anulable=Falso), Columna(‘nombre’, String( length=30), table=<cuenta_estudiante>), Column(‘edad’, Integer(), table=<cuenta_estudiante>), Column(‘calificación’, String(longitud=80), table=<cuenta_estudiante>), esquema =Ninguno), ‘elementos’: Tabla(‘elementos’, MetaData(), Columna(‘clave’, String(longitud=50), tabla=<elementos>, clave_principal=Verdadero, anulable=Falso), Columna(‘marca de tiempo ‘, DateTime(), table=<items>), Column(‘price’, Numeric(precision=100, scale=2), table=<items>), Column(‘type’, Enum(‘dry’, ‘ húmedo’), tabla=<elementos>), esquema=Ninguno)})

Acceso a claves de tablas:

Python3

metadata_object.tables.keys()

Producción:

dict_keys(['student_account', 'items'])

Declaración de restricciones

Como puede ver, hemos declarado la primera columna como clave principal en la tabla_estudiante. Ejecutar el siguiente comando mostrará los detalles de la restricción de clave principal.

Python3

student_table.primary_key

Producción:

PrimaryKeyConstraint(Column(‘id’, Integer(), table=<student_account>, primary_key=True, anulable=False))

Una restricción de clave principal normalmente se declara implícitamente, mientras que una ForeignKeyConstraint se declara explícitamente. Usamos restricciones de clave externa si dos tablas están relacionadas entre sí mediante el objeto ForeignKey.

Vamos a crear una nueva tabla llamada address_table que consta de la dirección de correo electrónico del estudiante y tendremos una restricción de clave externa que se refiere a la tabla de estudiantes.

Python3

from sqlalchemy import ForeignKey
 
address_table = Table(
     "address",
     metadata_object,
     Column('id', Integer, primary_key=True),
     Column('student_id', ForeignKey('student_account.id'), nullable=False),
     Column('email_address', String, nullable=False)
 )

Creación y eliminación de tablas

Crear tabla:

Hasta ahora hemos creado dos Tablas con un conjunto de Columnas y restricciones. Lo siguiente es que tenemos que emitir DDL a la base de datos SQLite (en este caso) para que podamos consultar con las tablas. Esto se puede hacer como se muestra a continuación:

Python3

from sqlalchemy import create_engine
 
# creating an engine object
engine = create_engine("sqlite+pysqlite:///:memory:",
                       echo=True, future=True)
# emitting DDL
metadata_object.create_all(engine)

Producción:

Mesa de caída

El método drop_all() se utiliza para eliminar todas las tablas en el objeto de metadatos.

Python

from sqlalchemy import create_engine
 
# creating an engine object
engine = create_engine("sqlite+pysqlite:///:memory:",
                       echo=True, future=True)
 
# emitting DDL
metadata_object.drop_all(engine)

Producción:

Describiendo bases de datos con metadatos: SQLAlchemy ORM

Aprenderemos a crear las mismas tablas que hemos creado usando Core con ORM. El ORM consta de clases mapeadas. Las clases asignadas se declaran de la misma manera que se crea cualquier clase de Python y vinculamos los atributos de las clases asignadas a las columnas de la tabla.

En ORM, el objeto MetaData se combina con el objeto ORM-Only llamado Registro. Construimos el Registro como se muestra a continuación:

Python3

from sqlalchemy.orm import registry
 
mapper_registry = registry()
mapper_registry.metadata

Producción:

MetaData()

En ORM, en lugar de declarar los objetos Table directamente, los declaramos indirectamente mediante el uso de clases asignadas. Las clases mapeadas descienden de un directorio base conocido como Base Declarativa. La base declarativa se puede crear usando el registro usando el método registration.generate_base().

Python3

Base = mapper_registry.generate_base()

Esta clase base sirve como clase base para las clases mapeadas de ORM que declaramos. Las dos tablas Student_account y address se pueden crear usando ORM como se muestra a continuación.

Python3

from sqlalchemy.orm import relationship
 
 
class Student(Base):
    __tablename__ = 'student_account'
    id = Column(Integer, primary_key=True)
    name = Column(String(30))
    age = Column(Integer)
    grade = Column(String)
 
    addresses = relationship("Address", back_populates="student")
 
    def __repr__(self):
        return f"Student(id={self.id!r}, name={self.name!r},\
        age={self.age!r},grade={self.grade!r})"
 
 
class Address(Base):
    __tablename__ = 'address'
    id = Column(Integer, primary_key=True)
    email_address = Column(String, nullable=False)
    student_id = Column(Integer, ForeignKey('student_account.id'))
 
    student = relationship("Student", back_populates="addresses")
 
    def __repr__(self):
        return f"Address(id={self.id!r}, email_address={self.email_address!r})"

El atributo .__table__ se usa para ver los objetos Table creados a partir de clases mapeadas declarativas, como se muestra a continuación:

Python3

Student.__table__

Producción:

Table('student_account', MetaData(), Column('id', Integer(),
 table=<student_account>, primary_key=True, nullable=False),
 Column('name', String(length=30), table=<student_account>),
 Column('age', Integer(), table=<student_account>),
 Column('grade', String(), table=<student_account>), schema=None)

Python3

Address.__table__

Producción:

Table('address', MetaData(), Column('id', Integer(),
 table=<address>, primary_key=True, nullable=False),
  Column('email_address', String(), table=<address>,
   nullable=False), Column('student_id', Integer(), 
   ForeignKey('student_account.id'), table=<address>), schema=None)

Emitiendo DDL:

En ORM, para emitir DDL usamos el objeto MetaData asociado con nuestro registro y la clase base declarativa ORM.

Python3

mapper_registry.metadata.create_all(engine)
 
Base.metadata.create_all(engine)

Producción:

Reflexión de la mesa

«Reflexión» se refiere a la carga de objetos de la tabla en función de la lectura de una tabla existente. Por ejemplo, crearemos un nuevo objeto Table que representa el objeto student_account que creamos manualmente en las secciones anteriores de este artículo como se muestra a continuación.

Python3

metadata2=MetaData()
with engine.connect() as conn:
    student_reflected=Table("student_account",
                            metadata2,
                            autoload_with=conn)

Producción:

Ahora puede acceder a las columnas de la tabla reflejada que acabamos de crear de la siguiente manera:

Python3

print(student_reflected.c)
print(student_reflected.primary_key)

Producción:

ImmutableColumnCollection(cuenta_estudiante.id, cuenta_estudiante.nombre, cuenta_estudiante.edad, cuenta_estudiante.grado)

PrimaryKeyConstraint(Column(‘id’, INTEGER(), table=<student_account>, primary_key=True, anulable=False))

Publicación traducida automáticamente

Artículo escrito por namaldesign y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

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