En esta plantilla, puede utilizar Postgres o SQLite como motor de base de datos. Verifique su archivo .env para especificar cuál desea utilizar. Puede utilizar la var env DATABASE_URL
para este propósito.
1$ psql
1\l
Nota: Si estás usando Gitpod, revisa el archivo
docs/assets/reset_migrations.bash
. Básicamente, estás creando una base de datos desde cero llamadaexample
.
1CREATE DATABASE example;
Nota: Asegúrese de actualizar DB_CONNECTION_STRING
en el archivo .env
con el nombre correcto de la base de datos.
Command
1\c example;
Result
1postgres=# \c example; 2Ahora estás conectado a la base de datos "example" como usuario "gitpod".
1\dt
users
:1select * from users;
Nota: Escriba
exit
si desea salir del terminal Postgres.
Para más comandos, puedes consultar este asombroso resumen.
La mayoría de las plantillas de 4Geeks Academy utilizan la librería SQLAlchemy para construir modelos, crear un modelo es muy sencillo:
1class Artist(db.Model): 2 id = db.Column(db.Integer, primary_key=True) 3 name = db.Column(db.String(80), nullable=False) 4 5 # Así es como el artista se imprimirá en la consola, sólo el nombre 6 def __repr__(self): 7 return self.name 8 9 # Este es el aspecto que tendrá el artista en las respuestas JSON de la API 10 def serialize(self): 11 return { 12 "id": self.id, 13 "name": self.name 14 }
He aquí algunos ejemplos de los distintos tipos de relaciones.
Una relación uno a muchos coloca una clave foránea en la tabla del hijo que hace referencia al padre.
db.relationship()
se especifica en el padre, como referencia a una colección de elementos representados por el hijo:
1class Artist(db.Model): 2 id = db.Column(db.Integer, primary_key=True) 3 name = db.Column(db.String(80), nullable=False) 4 5 # Un artista puede tener muchas grabaciones, y llamaremos a esta lista "records" 6 # esta es una clave externa que apunta al Record.id 7 records = db.relationship('Record', backref='parent',lazy=True) 8 9 def __repr__(self): 10 return self.name 11 12 def serialize(self): 13 return { 14 "id": self.id, 15 "name": self.name, 16 "records": list(map(lambda x: x.serialize(), self.records)) 17 } 18 19class Record(db.Model): 20 id = db.Column(db.Integer, primary_key=True) 21 name = db.Column(db.String(80), nullable=False) 22 23 # un registro sólo puede tener un artista, esto apunta al Artist.id 24 artist_id = db.Column(db.Integer, db.ForeignKey("parent.id"), nullable=False) 25 26 def __repr__(self): 27 return self.name 28 29 def serialize(self): 30 return { 31 "id": self.id, 32 "name": self.name 33 }
Muchos a Muchos añade una tabla de asociación entre dos clases. La tabla de asociación se indica mediante el argumento secundario de db.relationship()
.
Normalmente, la tabla utiliza el objeto MetaData asociado a la clase base declarativa, para que las directivas ForeignKey puedan localizar las tablas remotas con las que enlazar:
1association_table = db.Table('association', 2 db.Column("sister_id", db.Integer, db.ForeignKey("sister.id"), primary_key=True), 3 db.Column("brother_id", db.Integer, db.ForeignKey("brother.id"), primary_key=True) 4) 5 6class Sister(db.Model): 7 id = db.Column(Integer, primary_key=True) 8 name = db.Column(String(80), nullable=False) 9 brothers = db.relationship("Brother", 10 secondary=association_table, 11 back_populates="sisters") # this line is so it updates the field when Sister is updated 12 13 def __ref__(self): 14 return f'<Sister {self.name}>' 15 16 def serialize(self): 17 return { 18 "id": self.id, 19 "name": self.name, 20 "brothers": list(map(lambda x: x.serialize(), self.brothers)) 21 } 22 23class Brother(db.Model): 24 id = db.Column(Integer, primary_key=True) 25 name = db.Column(String(80), nullable=False) 26 sisters = db.relationship("Sister", 27 secondary=association_table, 28 back_populates="brothers") 29 30 def __ref__(self): 31 return f'<Brother {self.name}>' 32 33 def serialize(self): 34 return { 35 "id": self.id, 36 "name": self.name, 37 "sisters": list(map(lambda x: x.serialize(), self.sisters)) 38 }
Una vez que tu archivo models.py
esté listo, tienes que migrar
y actualizar
para poder sincronizar los cambios en tu motor de base de datos.
Este comando creará todos los archivos de migraciones en tu carpeta ./migrations
, de esta forma los tendremos confirmados en Github y todos los que trabajen en el proyecto tendrán exactamente la misma estructura de base de datos.
1$ pipenv run migrate
Nota: Es importante mencionar que el comando
migrate
no actualiza tu base de datos, tendrás queupgrade
si quieres realmente sincronizar los cambios en tu base de datos.
El comando de actualización echa un vistazo a los archivos de migraciones, y ejecuta todo lo que queda por ejecutar (fuera de sincronización) para asegurarse de que su base de datos está alineada con las migraciones.
1$ pipenv run upgrade
Al actualizar y migrar su base de datos, se encontrará con muchos errores. Aquí es donde resultan útiles los conocimientos de sintaxis SQL.
🛑 El botón del pánico: Hemos preparado este comando para ayudarte a poner a cero tu base de datos y tus migraciones.
1$ bash docs/assets/reset_migrations.bash
Hay muchas maneras de manipular bases de datos, pero hemos decidido utilizar Python y SQLAlchemy para hacerlo. Esto significa que no necesitas conocimientos de SQL, pero te recomendamos encarecidamente que aún así practiques y domines SQL con fines de depuración (la mayoría de los errores se muestran en lenguaje SQL)
Asumiendo que tienes un objeto Person en tu archivo models.py
.
1# conseguir a toda la gente 2people_query = Person.query.all() 3 4# obtener sólo los nombrados"Joe" 5people_query = Person.query.filter_by(name='Joe') 6 7# asigna los resultados y tu lista de personas dentro de la variable all_people 8all_people = list(map(lambda x: x.serialize(), people_query)) 9 10# conseguir una sola persona 11user1 = Person.query.get(person_id)
Asumiendo que tienes un objeto Person en tu fichero models.py
.
1user1 = Person(username="my_super_username", email="my_super@email.com") 2db.session.add(user1) 3db.session.commit()
1user1 = Person.query.get(person_id) 2if user1 is None: 3 raise APIException('User not found', status_code=404) 4 5if "username" in body: 6 user1.username = body["username"] 7if "email" in body: 8 user1.email = body["email"] 9db.session.commit()
1user1 = Person.query.get(person_id) 2if user1 is None: 3 raise APIException('User not found', status_code=404) 4db.session.delete(user1) 5db.session.commit()
Para más información, visite la siguiente página: https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/