| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
En la primera parte explicamos la modalidad de la materia en general. Las fechas de las entregas practicas serian las siguientes
En la segunda parte de la clase vimos un poco de python y hicimos una calculadora basica
Hicimos una calculadora media pedorra pero tuve algunos incovenientes con python porque no me acordaba mucho xd
Nota: \Esto no lo podemos usar si estamos en el main
import operationsPor lo que tenemos que hacer
Nota: \Esto no lo podemos usar si estamos en el main
from src import operationsEl profe empieza a explicar la practica del pdf asi por encima
Hablamos de la rama origin, hacemos referencia al repositorio remoto
git remote -vTambien usamos el comando
git push origin mainEl comando git push origin main es un comando de Git que permite enviar los cambios realizados en el repositorio local al repositorio remoto.
En este comando, origin se refiere al repositorio remoto donde se están enviando los cambios, y main se refiere a la rama del repositorio local que se está enviando al repositorio remoto.
Ahora si queremos crear una rama podemos hacer git branch y el nombre de la rama
git branch nombreRamay para subir los cambios
git push origin nombreRamaTambien usamos el git rebase
Clase 2 Aplicacion Base + DeployParece que ya no vemos nada importante, solo vemos como el profe va creando y fucionando las ramas, lo que si, podemos tener conflictos(o por lo menos yo) a la hora de hacer un pull en una rama que no es la main, por lo que tenemos que hacer un git pull origin main y despues un git push origin nombreRama
Vamos a levantar la aplicacion base para despues continuar con el trabajo integrador
Creamos el entorno virtual
El comando pyenv virtualenv 3.8.10 myenv que ejecutaste ha creado un entorno virtual de Python llamado "myenv" basado en la versión 3.8.10 de Python. Te proporcionaré algunos detalles adicionales sobre lo que hiciste y cómo puedes activar y desactivar este entorno virtual.
Creación del Entorno Virtual:
Activación del Entorno Virtual:
pyenv activate myenvDesactivación del Entorno Virtual:
pyenv deactivateEliminación del Entorno Virtual:
pyenv virtualenv-delete myenvRecuerda que, dentro de un entorno virtual, puedes instalar paquetes y dependencias específicos de ese proyecto sin afectar al entorno global de Python. Esto es útil para mantener la separación y la organización entre diferentes proyectos y sus dependencias.
Explicamos la infra
Cada uno trabaja en su rama, y despues hace un merge a main, y con esto, se ejecuta el 'ci' que es un script que nos permite hacer integracion continua.
Con este script de CI, cada vez que hagas un push en la rama principal, GitHub Actions construirá tu aplicación, instalará las dependencias, ejecutará las pruebas y te notificará si hay algún error. Asegúrate de ajustar las versiones y configuraciones según tu proyecto.
Como vamos a usar python 3.8.10, tenemos que instalarlo con pyenv para no tener problemas
pyenv install 3.8.10 # Instala Python 3.8.10 (por ejemplo)pyenv local myenv
Bien, una vez que tenemos nuestra aplicación base, vamos a hacer un deploy en Heroku
poetry new --name web --src admin
Agregamos el .gitignore
❯ poetry --version Poetry version 1.1.12
myenv seria el nombre del entorno virtual con la version de python que queremos usar
pyenv local myenv
poetry add flask@latest
poetry add --dev pytest@latest
Si abrimos el pyproject.toml, podemos ver que tenemos las dependencias que instalamos. En la seccion
[tool.poetry.dev-dependencies] pytest = "^7.4.2"
tenemos las dependencias de desarrollo
Como el trabajo es grupal, podemos clonar el repo y hacer
poetry install
Podemos cambiar la version de python de nuestro entorno con
poetry env use 3.8.10
Antes de esto tenia la 3.10
Y hacemos un, Para actualizar todo
poetry install
Usamos el siguiente comando para activar el entorno virtual
poetry shell
Para ver las versiones instaladas
flask --version Python 3.8.10 Flask 2.3.3 Werkzeug 2.3.7
Esto me lo detecto porque tengo flask instalado en mi entorno virtual
Si quiero ejecutar estos comandos sin la necesidad de usar el poetry shell, puedo hacer
poetry run flask --version
Una vez que tenemos todo instalado, hacemos nuestra pequeña app en el directorio src/web en el archivo init.py
from flask import Flask
def create_app():
app = Flask(__name__)
@app.get('/')
def home():
return 'Hello, World!'
return appY despues creamos un entrypoint en el directorio src/admin en el archivo app.py
En el contexto de Python y las aplicaciones que se distribuyen usando herramientas como setuptools o Poetry, un "entry point" (punto de entrada) se refiere a un punto específico en tu código donde la ejecución de tu programa comienza.
from src.web import create_app
app = create_app()
if __name__ == '__main__':
app.run()Una vez que tenemos nuestra app, podemos ejecutar
flask run
Y me tira la ip http://127.0.0.1:5000/
El decorador
@app.get('/')Encierra una funcion que se ejecuta cuando se hace un get a la ruta /
Podemos ejecutar el modo debug para no tener que actualizar el servidor cada vez que hacemos un cambio
flask run --debuug
Ya que tenemos el pytest instalado, vamos a hacer un mini test en la carpeta tests
from web import create_app
app = create_app()
app.testing = True
cliente = app.test_client()
def test_home():
response = cliente.get('/')
assert response.status_code == 200
assert "Hello, World!" in response.data.decode('utf-8')Este test lo podemos ejecutar con
pytest
Una vez que tenemos los test, creamos una carpeta dentro de /src/web llamada template que pondremos los archivos html y tambien creamos la carpeta static en el /src/ para los archivos estaticos que en este caso son los archivos css para todas las paginas
El archivo init.py quedaria asi
from flask import Flask, render_template
def create_app(env='development', static_folder='../../static'):
app = Flask(__name__, static_folder=static_folder)
@app.get('/')
def home():
return render_template('home.html')
@app.get('/about')
def about():
return render_template('about.html')
@app.get('/contact')
def contact():
return render_template('contact.html')
@app.errorhandler(404)
def page_not_found(e):
return render_template('error.html', error_code='404', error_message='Página no encontrada'), 404
return appPor ultimo lo subimos a produccion
git init git add . git commit -m "first commit" git branch -M main git remote add origin
Agregamos un controlador para mostrar en nuestra pagina una lista de issues(consultas/tickets). En core creamos un archivo board (tablero) en el que harcodeamos nuestras consultas ya que de momento no tenemos acceso a una base de datos.
Datos generados con chat-gpt
def list_issues():
"""List all issues."""
issues = [
{
'id': 1,
'email': 'john.doe@example.com',
'description': 'Unable to log in to the application.',
'status': 'new'
},
{
'id': 2,
'email': 'sara.jones@example.com',
'description': 'App crashes when navigating to the settings page.',
'status': 'in-progress'
},
{
'id': 3,
'email': 'mark.smith@example.com',
'description': 'Feature request: Add dark mode to the application.',
'status': 'resolved'
},
{
'id': 4,
'email': 'lisa.johnson@example.com',
'description': 'Error 404 when trying to access a specific URL.',
'status': 'new'
},
{
'id': 5,
'email': 'peter.wilson@example.com',
'description': 'Performance issue: Application takes too long to load.',
'status': 'in-progress'
},
{
'id': 6,
'email': 'mary.brown@example.com',
'description': 'Bug: Incorrect data displayed in the user profile.',
'status': 'resolved'
},
{
'id': 7,
'email': 'alex.miller@example.com',
'description': 'Feature request: Integrate with third-party API for weather information.',
'status': 'new'
},
{
'id': 8,
'email': 'chris.white@example.com',
'description': 'App freezes when attempting to upload large files.',
'status': 'in-progress'
},
{
'id': 9,
'email': 'emily.jones@example.com',
'description': 'Bug: Unable to delete account from profile settings.',
'status': 'resolved'
},
{
'id': 10,
'email': 'david.taylor@example.com',
'description': 'Feature request: Implement a chat feature within the application.',
'status': 'new'
}
]
return issuesEsto en el futuro lo cambiamos por las consultas a la base de datos
Dentro de web creamos la carpeta controllers con el archivo issues.py
El Blueprint es una forma de organizar las rutas
from flask import render_template
from src.core import board
from flask import Blueprint
issues_bp = Blueprint('issues', __name__, url_prefix='/consultas')
@issues_bp.get('/')
def index():
issues = board.list_issues()
return render_template('issues/index.html', issues=issues)El issues_bp despues lo importamos en el __init__.py de web y lo registramos. Esto nos permite definir las rutas en el archivo issues.py y no en el __init__.py de web
Despues de esto, tenemos que crear una carpeta en templates con el nombre issues y dentro un archivo index.html
{% extends 'layout.html' %}
{% block head %}<link rel="stylesheet" href="{{ url_for('static', filename='issues.css') }}"> {% endblock %}
{% block title %}Consultas{% endblock %}
{% block header %}
{{ super() }}
{% endblock %}
{% block content %}
<h1>Issues</h1>
<table class="index-table box">
<thead>
<tr>
<th>ID</th>
<th>Email</th>
<th>Description</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for issue in issues %}
<tr>
<td>{{ issue.id }}</td>
<td>{{ issue.email }}</td>
<td>{{ issue.description }}</td>
<td>{{ issue.status }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}El archivo __init__.py quedaria asi
from flask import Flask, render_template
from src.web.controllers.issues import issues_bp
from src.web.config import config
def create_app(env='dev', static_folder='../../static'):
app = Flask(__name__, static_folder=static_folder)
app.config.from_object(config[env])
app.register_blueprint(issues_bp)
@app.get('/')
def home():
return render_template('home.html')
@app.get('/about')
def about():
return render_template('about.html')
@app.get('/contact')
def contact():
return render_template('contact.html')
@app.get('/consultas')
def ussues():
return render_template('issues/index.html')
@app.errorhandler(404)
def page_not_found(e):
return render_template('error.html', error_code='404', error_message='Página no encontrada'), 404
return appla linea
app.register_blueprint(issues_bp)es la que nos permite registrar el blueprint que creamos en el archivo issues.py
Para configurar todos estos entornos creamos un archivo dentro de web llamado config.py
class Config(object):
"""Base config"""
SECRET_KEY='secret'
TESTING=False
SESSION_TYPE='filesystem'
class ProdConfig(Config):
pass
class DevConfig(Config):
pass
class TestConfig(Config):
TESTING=True
pass
config = {
'dev': DevConfig,
'prod': ProdConfig,
'test': TestConfig
}Importamos el archivo config.py en el __init__.py de web
app.config.from_object(config[env])Por ultimo tenemso que modificar __init__.py de la carpeta test para que reciba el entorno de test
from flask import Flask, render_template
from web import create_app
app = create_app(env='test')
cliente = app.test_client()Primero instalamos un par de librerias para conectarnos a la base de datos
poetry add psycopg2-binary@latest poetry add flask_sqlalchemy@latest
Y ahora instalamos una libreria porque si
poetry add flask-shell-ipython@latest --group dev
Es una consola un poco mas interactiva y despues hacemos un
flask shell
Despues en core creamos un archivo dentro de core llamado database.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def init_app(app):
db.init_app(app)Y la importamos en el __init__.py de web
from src.core import database con las siguiente linea dentro de create_app
database.init_app(app)Ahora configuramos la base con algunos metodos que queremos que tenga la base de datos
Ahora agregamos a database.py los siguientes metodos
def config_db(app):
"""
Configuracion de la aplicacion
"""
@app.teardown_request
def close_session(exception=None):
db.session.close()Sirve para que cada vez que se haga una peticion a la base de datos, se cierre la conexion
def reset_database():
"""
Reinicia la base de datos
"""
db.drop_all()
db.create_all()Este metodo nos sirve para reiniciar la base de datos
Ahora pasamos a una parte en la que el profe nos explica como personalzar comandos, desde el __init__.py de web agregamos lo siguiente al final ded la funcion create_app
@app.cli.command(name='reset-database')
def resertdb():
"""
Comando para reiniciar la base de datos
"""
database.reset_database()Esto me crea un comando que llama a database y ejecuto su respectiva funcion
Y podemos ejecutar el simplemente el comando usando
flask resertdb
Bien, puede que el comando no funcione pero es porque todavia no tenemos la base de datos configurada
Ahora vamos a configurar la base de datos, y en config.py y agregamos lo siguiente
class DevConfig(Config):
DB_USER = "postgres"
DB_PASSWORD = "postgres"
DB_HOST = "localhost"
DB_NAME = "proyecto"
SQLALCHEMY_TRACK_MODIFICATIONS = True
SQLALCHEMY_DATABASE_URI = (
f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}/{DB_NAME}"
)| Back | FazBrowse Home | New Git URL |