diff --git a/Backend/FastAPI/db/client.py b/Backend/FastAPI/db/client.py index bfccb67b..d92a3616 100644 --- a/Backend/FastAPI/db/client.py +++ b/Backend/FastAPI/db/client.py @@ -22,5 +22,10 @@ # "mongodb+srv://:@/?retryWrites=true&w=majority").test # Despliegue API en la nube: -# Deta - https://www.deta.sh/ -# Intrucciones - https://fastapi.tiangolo.com/deployment/deta/ +# Deta (deprecado) - https://www.deta.sh/ +# Vercel - https://www.vercel.com +# Instrucciones - https://cleverzone.medium.com/fastapi-deployment-into-vercel-0fa4e6478014 +# MUY IMPORTANTE - Al desplegar en producción, preparar el proyecto para trabajar con variables de entorno que hagan referencia a datos sensibles: +# - Nunca subas a un repositorio público el valor de las variables +# - Puedes usar dotenv en Python +# - Añade el valor de las variables desde el proveedor de hosting diff --git a/Backend/FastAPI/db/models/user.py b/Backend/FastAPI/db/models/user.py index b26dc09a..73d57665 100644 --- a/Backend/FastAPI/db/models/user.py +++ b/Backend/FastAPI/db/models/user.py @@ -7,6 +7,6 @@ class User(BaseModel): - id: Optional[str] + id: Optional[str] = None username: str email: str diff --git a/Backend/FastAPI/main.py b/Backend/FastAPI/main.py index 09d72fa5..c8ba0830 100644 --- a/Backend/FastAPI/main.py +++ b/Backend/FastAPI/main.py @@ -9,6 +9,7 @@ from fastapi import FastAPI from routers import products, users, basic_auth_users, jwt_auth_users, users_db from fastapi.staticfiles import StaticFiles +import os app = FastAPI() diff --git a/Backend/FastAPI/requirements.txt b/Backend/FastAPI/requirements.txt index 8ab51608..8fa41bc8 100644 --- a/Backend/FastAPI/requirements.txt +++ b/Backend/FastAPI/requirements.txt @@ -1,7 +1,5 @@ -# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=27335 -fastapi +fastapi[standard] python-jose passlib bcrypt -pymongo -python-multipart \ No newline at end of file +pymongo \ No newline at end of file diff --git a/Backend/FastAPI/routers/basic_auth_users.py b/Backend/FastAPI/routers/basic_auth_users.py index 054b991d..da1b0f20 100644 --- a/Backend/FastAPI/routers/basic_auth_users.py +++ b/Backend/FastAPI/routers/basic_auth_users.py @@ -6,9 +6,11 @@ from pydantic import BaseModel from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -router = APIRouter(prefix="/basicauth", - tags=["basicauth"], - responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}}) +router = APIRouter( + prefix="/basicauth", + tags=["basicauth"], + responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}} +) oauth2 = OAuth2PasswordBearer(tokenUrl="login") @@ -28,14 +30,14 @@ class UserDB(User): "mouredev": { "username": "mouredev", "full_name": "Brais Moure", - "email": "braismoure@mourede.com", + "email": "braismoure@mouredev.com", "disabled": False, "password": "123456" }, "mouredev2": { "username": "mouredev2", "full_name": "Brais Moure 2", - "email": "braismoure2@mourede.com", + "email": "braismoure2@mouredev.com", "disabled": True, "password": "654321" } diff --git a/Backend/FastAPI/routers/jwt_auth_users.py b/Backend/FastAPI/routers/jwt_auth_users.py index c942b0c6..dd266882 100644 --- a/Backend/FastAPI/routers/jwt_auth_users.py +++ b/Backend/FastAPI/routers/jwt_auth_users.py @@ -7,15 +7,17 @@ from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jose import jwt, JWTError from passlib.context import CryptContext -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone ALGORITHM = "HS256" ACCESS_TOKEN_DURATION = 1 SECRET = "201d573bd7d1344d3a3bfce1550b69102fd11be3db6d379508b6cccc58ea230b" -router = APIRouter(prefix="/jwtauth", - tags=["jwtauth"], - responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}}) +router = APIRouter( + prefix="/jwtauth", + tags=["jwtauth"], + responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}} +) oauth2 = OAuth2PasswordBearer(tokenUrl="login") @@ -37,14 +39,14 @@ class UserDB(User): "mouredev": { "username": "mouredev", "full_name": "Brais Moure", - "email": "braismoure@mourede.com", + "email": "braismoure@mouredev.com", "disabled": False, "password": "$2a$12$B2Gq.Dps1WYf2t57eiIKjO4DXC3IUMUXISJF62bSRiFfqMdOI2Xa6" }, "mouredev2": { "username": "mouredev2", "full_name": "Brais Moure 2", - "email": "braismoure2@mourede.com", + "email": "braismoure2@mouredev.com", "disabled": True, "password": "$2a$12$SduE7dE.i3/ygwd0Kol8bOFvEABaoOOlC8JsCSr6wpwB4zl5STU4S" } @@ -103,7 +105,7 @@ async def login(form: OAuth2PasswordRequestForm = Depends()): status_code=status.HTTP_400_BAD_REQUEST, detail="La contraseña no es correcta") access_token = {"sub": user.username, - "exp": datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_DURATION)} + "exp": datetime.now(timezone.utc) + timedelta(minutes=ACCESS_TOKEN_DURATION)} return {"access_token": jwt.encode(access_token, SECRET, algorithm=ALGORITHM), "token_type": "bearer"} diff --git a/Backend/FastAPI/routers/products.py b/Backend/FastAPI/routers/products.py index 6d85b336..4562224c 100644 --- a/Backend/FastAPI/routers/products.py +++ b/Backend/FastAPI/routers/products.py @@ -4,12 +4,13 @@ from fastapi import APIRouter -router = APIRouter(prefix="/products", - tags=["products"], - responses={404: {"message": "No encontrado"}}) +router = APIRouter( + prefix="/products", + tags=["products"], + responses={404: {"message": "No encontrado"}} +) -products_list = ["Producto 1", "Producto 2", - "Producto 3", "Producto 4", "Producto 5"] +products_list = ["Producto 1", "Producto 2", "Producto 3", "Producto 4", "Producto 5"] @router.get("/") diff --git a/Backend/FastAPI/routers/users_db.py b/Backend/FastAPI/routers/users_db.py index 7e61d751..1b5645ff 100644 --- a/Backend/FastAPI/routers/users_db.py +++ b/Backend/FastAPI/routers/users_db.py @@ -8,9 +8,10 @@ from db.client import db_client from bson import ObjectId -router = APIRouter(prefix="/userdb", - tags=["userdb"], - responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}}) +router = APIRouter( + prefix="/userdb", + tags=["userdb"], + responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}}) @router.get("/", response_model=list[User]) diff --git a/Backend/FastAPI/vercel.json b/Backend/FastAPI/vercel.json new file mode 100644 index 00000000..10bc3cd6 --- /dev/null +++ b/Backend/FastAPI/vercel.json @@ -0,0 +1,14 @@ +{ + "builds": [ + { + "src": "main.py", + "use": "@vercel/python" + } + ], + "routes": [ + { + "src": "/(.*)", + "dest": "main.py" + } + ] +} \ No newline at end of file diff --git a/Basic/09_loops.py b/Basic/09_loops.py index b7d476a9..6db69d9b 100644 --- a/Basic/09_loops.py +++ b/Basic/09_loops.py @@ -47,7 +47,7 @@ if element == "Edad": break else: - print("El bluce for para diccionario ha finalizado") + print("El bucle for para el diccionario ha finalizado") print("La ejecución continúa") diff --git a/Basic/11_classes.py b/Basic/11_classes.py index ec3c2eca..28e84692 100644 --- a/Basic/11_classes.py +++ b/Basic/11_classes.py @@ -11,7 +11,7 @@ class MyEmptyPerson: print(MyEmptyPerson) print(MyEmptyPerson()) -# Clase con constructor, funciones y popiedades privadas y públicas +# Clase con constructor, funciones y propiedades privadas y públicas class Person: diff --git a/Images/pro.jpg b/Images/pro.jpg new file mode 100644 index 00000000..986b7705 Binary files /dev/null and b/Images/pro.jpg differ diff --git a/Intermediate/02_challenges.py b/Intermediate/02_challenges.py index 36bef0a1..a816e676 100644 --- a/Intermediate/02_challenges.py +++ b/Intermediate/02_challenges.py @@ -16,7 +16,7 @@ def fizzbuzz(): for index in range(1, 101): if index % 3 == 0 and index % 5 == 0: - print("fizzbuz") + print("fizzbuzz") elif index % 3 == 0: print("fizz") elif index % 5 == 0: diff --git a/Intermediate/03_lambdas.py b/Intermediate/03_lambdas.py index d23507ac..d51f8fda 100644 --- a/Intermediate/03_lambdas.py +++ b/Intermediate/03_lambdas.py @@ -2,22 +2,13 @@ ### Lambdas ### -def sum_two_values( - first_value, second_value): return first_value + second_value - - +sum_two_values = lambda first_value, second_value: first_value + second_value print(sum_two_values(2, 4)) - -def multiply_values( - first_value, second_value): return first_value * second_value - 3 - - +multiply_values = lambda first_value, second_value: first_value * second_value - 3 print(multiply_values(2, 4)) - def sum_three_values(value): return lambda first_value, second_value: first_value + second_value + value - -print(sum_three_values(5)(2, 4)) +print(sum_three_values(5)(2, 4)) \ No newline at end of file diff --git a/Intermediate/05_error_types.py b/Intermediate/05_error_types.py index 853f329e..62566c8d 100644 --- a/Intermediate/05_error_types.py +++ b/Intermediate/05_error_types.py @@ -42,8 +42,8 @@ print(pi) # ValueError -#my_int = int("10 Años") -my_int = int("10") # Descomentar para Error +# my_int = int("10 Años") # Descomentar para Error +my_int = int("10") print(type(my_int)) # ZeroDivisionError diff --git a/Intermediate/06_file_handling.py b/Intermediate/06_file_handling.py index 05ab8df1..3bf072b0 100644 --- a/Intermediate/06_file_handling.py +++ b/Intermediate/06_file_handling.py @@ -10,33 +10,49 @@ # .txt file # Leer, escribir y sobrescribir si ya existe -txt_file = open("Intermediate/my_file.txt", "w+") +txt_file = open("my_file.txt", "w+") txt_file.write( "Mi nombre es Brais\nMi apellido es Moure\n35 años\nY mi lenguaje preferido es Python") -# print(txt_file.read()) +# Posiciona el cursor al inicio del fichero +txt_file.seek(0) + +# Lee e imprime todo el contenido del fichero +print(txt_file.read()) + +# Lee e imprime 10 caracteres desde el inicio del fichero +txt_file.seek(0) print(txt_file.read(10)) + +# Lee e imprime el resto de la línea actual desde la posición 11 print(txt_file.readline()) + +# Lee e imprime la siguiente línea print(txt_file.readline()) + +# Lee e imprime las líneas restantes del fichero for line in txt_file.readlines(): print(line) +# Escribe una nueva línea en el fichero txt_file.write("\nAunque también me gusta Kotlin") -print(txt_file.readline()) +# Posiciona el cursor al inicio del fichero, lee e imprime todo su contenido +txt_file.seek(0) +print(txt_file.read()) + +# Cierra el fichero txt_file.close() -with open("Intermediate/my_file.txt", "a") as my_other_file: +# Agrega una nueva línea en el fichero +with open("my_file.txt", "a") as my_other_file: my_other_file.write("\nY Swift") # os.remove("Intermediate/my_file.txt") -# Clase en vídeo (03/11/22): https://www.twitch.tv/videos/1642512950 - # .json file - json_file = open("Intermediate/my_file.json", "w+") json_test = { diff --git a/Intermediate/07_regular_expressions.py b/Intermediate/07_regular_expressions.py index d2b1f9a7..086d79bd 100644 --- a/Intermediate/07_regular_expressions.py +++ b/Intermediate/07_regular_expressions.py @@ -45,8 +45,6 @@ print(re.sub("[l|L]ección", "LECCIÓN", my_string)) print(re.sub("Expresiones Regulares", "RegEx", my_string)) -# Clase en vídeo (09/11/22): https://www.twitch.tv/videos/1648023317 - ### Regular Expressions Patterns ### # Para aprender y validar expresiones regulares: https://regex101.com diff --git a/README.md b/README.md index 2dafc69c..c423682a 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,8 @@ ![](./Images/header.jpg) ### Proyecto realizado durante emisiones en directo desde [Twitch](https://twitch.tv/mouredev) -> ##### Si consideras útil el curso, apóyalo haciendo "★ Star" en el repositorio. ¡Gracias! - -## ¡NUEVO! Curso de Python para web - -[![Curso Python Web](https://img.shields.io/github/stars/mouredev/python-web?label=Curso%20Python%20web&style=social)](https://github.com/mouredev/python-web) - +> ##### Si consideras útil el curso, apóyalo haciendo "★ Star" en el repositorio. ¡Gracias! ## Clases en vídeo @@ -29,44 +24,44 @@ Curso que agrupa todas las clases en directo que hacen referencia a los fundamen -* [Introducción](https://youtu.be/Kp4Mvapo5kc) -* [Contexto](https://youtu.be/Kp4Mvapo5kc?t=244) -* [Lección 1 - Configuración](https://youtu.be/Kp4Mvapo5kc?t=850) -* [Lección 2 - Hola Mundo](https://youtu.be/Kp4Mvapo5kc?t=1518) -* [Lección 3 - Variables](https://youtu.be/Kp4Mvapo5kc?t=2938) -* [Lección 4 - Operadores](https://youtu.be/Kp4Mvapo5kc?t=5665) -* [Lección 5 - Strings](https://youtu.be/Kp4Mvapo5kc?t=8643) -* [Lección 6 - Listas](https://youtu.be/Kp4Mvapo5kc?t=10872) -* [Lección 7 - Tuplas](https://youtu.be/Kp4Mvapo5kc?t=14711) -* [Lección 8 - Sets](https://youtu.be/Kp4Mvapo5kc?t=16335) -* [Lección 9 - Diccionarios](https://youtu.be/Kp4Mvapo5kc?t=18506) -* [Lección 10 - Condicionales](https://youtu.be/Kp4Mvapo5kc?t=21442) -* [Lección 11 - Bucles/Loops/Ciclos](https://youtu.be/Kp4Mvapo5kc?t=23822) -* [Lección 12 - Funciones](https://youtu.be/Kp4Mvapo5kc?t=26619) -* [Lección 13 - Clases](https://youtu.be/Kp4Mvapo5kc?t=29327) -* [Lección 14 - Excepciones](https://youtu.be/Kp4Mvapo5kc?t=32030) -* [Lección 15 - Módulos](https://youtu.be/Kp4Mvapo5kc?t=34583) -* [Próximos pasos](https://youtu.be/Kp4Mvapo5kc?t=36390) +- [Introducción](https://youtu.be/Kp4Mvapo5kc) +- [Contexto](https://youtu.be/Kp4Mvapo5kc?t=244) +- [Lección 1 - Configuración](https://youtu.be/Kp4Mvapo5kc?t=850) +- [Lección 2 - Hola Mundo](https://youtu.be/Kp4Mvapo5kc?t=1518) +- [Lección 3 - Variables](https://youtu.be/Kp4Mvapo5kc?t=2938) +- [Lección 4 - Operadores](https://youtu.be/Kp4Mvapo5kc?t=5665) +- [Lección 5 - Strings](https://youtu.be/Kp4Mvapo5kc?t=8643) +- [Lección 6 - Listas](https://youtu.be/Kp4Mvapo5kc?t=10872) +- [Lección 7 - Tuplas](https://youtu.be/Kp4Mvapo5kc?t=14711) +- [Lección 8 - Sets](https://youtu.be/Kp4Mvapo5kc?t=16335) +- [Lección 9 - Diccionarios](https://youtu.be/Kp4Mvapo5kc?t=18506) +- [Lección 10 - Condicionales](https://youtu.be/Kp4Mvapo5kc?t=21442) +- [Lección 11 - Bucles/Loops/Ciclos](https://youtu.be/Kp4Mvapo5kc?t=23822) +- [Lección 12 - Funciones](https://youtu.be/Kp4Mvapo5kc?t=26619) +- [Lección 13 - Clases](https://youtu.be/Kp4Mvapo5kc?t=29327) +- [Lección 14 - Excepciones](https://youtu.be/Kp4Mvapo5kc?t=32030) +- [Lección 15 - Módulos](https://youtu.be/Kp4Mvapo5kc?t=34583) +- [Próximos pasos](https://youtu.be/Kp4Mvapo5kc?t=36390) ### Curso intermedio de fundamentos desde cero Curso en el que continuamos aprendiendo Python desde sus bases, siguiendo la ruta de aprendizaje desde la última lección del curso de inicial. > Código: Directorio "Intermediate" en el proyecto - + -* [Introducción](https://youtu.be/TbcEqkabAWU) -* [Lección 1 - Dates](https://youtu.be/TbcEqkabAWU?t=202) -* [Lección 2 - List Comprehension](https://youtu.be/TbcEqkabAWU?t=3239) -* [Lección 3 - Resolución de retos de programación](https://youtu.be/TbcEqkabAWU?t=4142) -* [Lección 4 - Lambdas](https://youtu.be/TbcEqkabAWU?t=9145) -* [Lección 5 - Funciones de orden superior](https://youtu.be/TbcEqkabAWU?t=10172) -* [Lección 6 - Tipos de error](https://youtu.be/TbcEqkabAWU?t=12721) -* [Lección 7 - Manejo de ficheros](https://youtu.be/TbcEqkabAWU?t=15524) -* [Lección 8 - Expresiones regulares](https://youtu.be/TbcEqkabAWU?t=19762) -* [Lección 9 - Manejo de paquetes](https://youtu.be/TbcEqkabAWU?t=24010) -* [Próximos pasos](https://youtu.be/TbcEqkabAWU?t=26228) +- [Introducción](https://youtu.be/TbcEqkabAWU) +- [Lección 1 - Dates](https://youtu.be/TbcEqkabAWU?t=202) +- [Lección 2 - List Comprehension](https://youtu.be/TbcEqkabAWU?t=3239) +- [Lección 3 - Resolución de retos de programación](https://youtu.be/TbcEqkabAWU?t=4142) +- [Lección 4 - Lambdas](https://youtu.be/TbcEqkabAWU?t=9145) +- [Lección 5 - Funciones de orden superior](https://youtu.be/TbcEqkabAWU?t=10172) +- [Lección 6 - Tipos de error](https://youtu.be/TbcEqkabAWU?t=12721) +- [Lección 7 - Manejo de ficheros](https://youtu.be/TbcEqkabAWU?t=15524) +- [Lección 8 - Expresiones regulares](https://youtu.be/TbcEqkabAWU?t=19762) +- [Lección 9 - Manejo de paquetes](https://youtu.be/TbcEqkabAWU?t=24010) +- [Próximos pasos](https://youtu.be/TbcEqkabAWU?t=26228) ### Backend desde cero @@ -76,28 +71,28 @@ Curso en el que aprenderemos a utilizar Python para backend e implementaremos un -* [Introducción](https://youtu.be/_y9qQZXE24A) -* [Lección 01 - ¿Qué es un backend?](https://youtu.be/_y9qQZXE24A?t=125) -* [Lección 02 - API y FastAPI](https://youtu.be/_y9qQZXE24A?t=834) -* [Lección 03 - Type Hints](https://youtu.be/_y9qQZXE24A?t=1810) -* [Lección 04 - Configuración FastAPI](https://youtu.be/_y9qQZXE24A?t=2629) -* [Lección 05 - Hola mundo](https://youtu.be/_y9qQZXE24A?t=3504) -* [Lección 06 - Operación GET](https://youtu.be/_y9qQZXE24A?t=5382) -* [Lección 07 - Peticiones HTTP](https://youtu.be/_y9qQZXE24A?t=5925) -* [Lección 08 - Creación API](https://youtu.be/_y9qQZXE24A?t=6099) -* [Lección 09 - Path y Query](https://youtu.be/_y9qQZXE24A?t=7510) -* [Lección 10 - Operaciones POST, PUT y DELETE](https://youtu.be/_y9qQZXE24A?t=8529) -* [Lección 11 - HTTP status codes](https://youtu.be/_y9qQZXE24A?t=11072) -* [Lección 12 - Routers](https://youtu.be/_y9qQZXE24A?t=12475) -* [Lección 13 - Recursos estáticos](https://youtu.be/_y9qQZXE24A?t=13618) -* [Lección 14 - Autorización OAuth2](https://youtu.be/_y9qQZXE24A?t=14094) -* [Lección 15 - OAuth2 JWT](https://youtu.be/_y9qQZXE24A?t=17664) -* [Lección 16 - MongoDB](https://youtu.be/_y9qQZXE24A?t=20480) -* [Lección 17 - MongoDB Atlas](https://youtu.be/_y9qQZXE24A?t=25470) -* [Lección 18 - Despliegue en Deta *](https://youtu.be/_y9qQZXE24A?t=27335) -* [Próximos pasos](https://youtu.be/_y9qQZXE24A?t=28484) - -***ACTUALIZACIÓN Sobre la lección 18:** Deta ha actualizado ligeramente su servicio de despliegue de aplicaciones con FastAPI. Tienes toda la documentación [aquí](https://deta.space/docs/en/quickstart-guides/python#fastapi). También han creado una [guía de migración](https://deta.space/migration/guides/migrate-a-micro/). +- [Introducción](https://youtu.be/_y9qQZXE24A) +- [Lección 01 - ¿Qué es un backend?](https://youtu.be/_y9qQZXE24A?t=125) +- [Lección 02 - API y FastAPI](https://youtu.be/_y9qQZXE24A?t=834) +- [Lección 03 - Type Hints](https://youtu.be/_y9qQZXE24A?t=1810) +- [Lección 04 - Configuración FastAPI](https://youtu.be/_y9qQZXE24A?t=2629) +- [Lección 05 - Hola mundo](https://youtu.be/_y9qQZXE24A?t=3504) +- [Lección 06 - Operación GET](https://youtu.be/_y9qQZXE24A?t=5382) +- [Lección 07 - Peticiones HTTP](https://youtu.be/_y9qQZXE24A?t=5925) +- [Lección 08 - Creación API](https://youtu.be/_y9qQZXE24A?t=6099) +- [Lección 09 - Path y Query](https://youtu.be/_y9qQZXE24A?t=7510) +- [Lección 10 - Operaciones POST, PUT y DELETE](https://youtu.be/_y9qQZXE24A?t=8529) +- [Lección 11 - HTTP status codes](https://youtu.be/_y9qQZXE24A?t=11072) +- [Lección 12 - Routers](https://youtu.be/_y9qQZXE24A?t=12475) +- [Lección 13 - Recursos estáticos](https://youtu.be/_y9qQZXE24A?t=13618) +- [Lección 14 - Autorización OAuth2](https://youtu.be/_y9qQZXE24A?t=14094) +- [Lección 15 - OAuth2 JWT](https://youtu.be/_y9qQZXE24A?t=17664) +- [Lección 16 - MongoDB](https://youtu.be/_y9qQZXE24A?t=20480) +- [Lección 17 - MongoDB Atlas](https://youtu.be/_y9qQZXE24A?t=25470) +- [Lección 18 - Despliegue en Deta \*](https://youtu.be/_y9qQZXE24A?t=27335) +- [Próximos pasos](https://youtu.be/_y9qQZXE24A?t=28484) + +**\*ACTUALIZACIÓN Sobre la lección 18:** Deta, el servicio utilizado para el despliegue durante el curso, ya no existe. Te recomiendo revisar la documentación oficial de FastAPI sobre [despliegue](https://fastapi.tiangolo.com/deployment/). Puedes utilizar alguno de los [proveedores gratuitos](https://fastapi.tiangolo.com/deployment/cloud/) recomendados. En mi caso, te dejo el [fichero de configuración](./Backend/FastAPI/vercel.json) y el de [dependencias](./Backend/FastAPI/requirements.txt) para hacerlo desde [Vercel](https://vercel.com/) (al crear el proyecto en la plataforma selecciona que el directorio "Backend/FastAPI" es el root). ### Frontend desde cero @@ -146,29 +141,34 @@ Y para finalizar... ¿Quieres saber aun más sobre él? Aquí tienes 15 curiosid Actualmente el curso está en pausa. Se han finalizados los bloques básico, intermedio y backend, y ese era el objetivo inicial del proyecto. No descarto añadir nuevas lecciones a futuro, pero creo que por el momento puede servir de base a cualquier persona que quiera empezar a aprender este lenguaje. -* Recuerda que he creado en el [Discord](https://discord.gg/mouredev) un canal "🐍python" para que puedas comentar lo que quieras. -* En el momento que el curso continúe, actualizaré el repositorio y avisaré en redes. +- Recuerda que he creado en el [Discord](https://discord.gg/mouredev) un canal "🐍python" para que puedas comentar lo que quieras. +- En el momento que el curso continúe, actualizaré el repositorio y avisaré en redes. ¡Muchísimas gracias por todo el apoyo mostrado! ## Enlaces de interés -* [Web oficial de Python](https://www.python.org/) -* [Tutorial oficial de Python en Español](https://docs.python.org/es/3/tutorial/index.html) -* [Repo 30 días de Python](https://github.com/Asabeneh/30-Days-Of-Python) -* [Juego Codédex para aprender Python](https://www.codedex.io/) -* [Visual Studio Code](https://code.visualstudio.com/): El editor que estoy usando -* [FastAPI](https://fastapi.tiangolo.com/es/): El framework para crear nuestra API Backend -* [MongoDB](https://www.mongodb.com/): La base de datos que utiliza nuestro backend -* [Deta](https://www.deta.sh/): Para desplegar nuestra API en la nube +- [Web oficial de Python](https://www.python.org/) +- [Tutorial oficial de Python en Español](https://docs.python.org/es/3/tutorial/index.html) +- [Repo 30 días de Python](https://github.com/Asabeneh/30-Days-Of-Python) +- [Juego Codédex para aprender Python](https://www.codedex.io/) +- [Visual Studio Code](https://code.visualstudio.com/): El editor que estoy usando +- [FastAPI](https://fastapi.tiangolo.com/es/): El framework para crear nuestra API Backend +- [MongoDB](https://www.mongodb.com/): La base de datos que utiliza nuestro backend +- [Vercel](https://vercel.com/): Para desplegar nuestra API en la nube -Si quieres unirte a nuestra comunidad de desarrollo, aprender programación de Apps, mejorar tus habilidades y ayudar a la continuidad del proyecto, puedes encontrarnos en: +## Únete al campus de programación de la comunidad -[![Twitch](https://img.shields.io/badge/Twitch-Programación_en_directo-9146FF?style=for-the-badge&logo=twitch&logoColor=white&labelColor=101010)](https://twitch.tv/mouredev) -[![Discord](https://img.shields.io/badge/Discord-Servidor_de_la_comunidad-5865F2?style=for-the-badge&logo=discord&logoColor=white&labelColor=101010)](https://mouredev.com/discord) -[![Link](https://img.shields.io/badge/Links_de_interés-moure.dev-39E09B?style=for-the-badge&logo=Linktree&logoColor=white&labelColor=101010)](https://moure.dev) +![https://mouredev.pro](./Images/pro.jpg) + +#### Te presento [mouredev pro](https://mouredev.pro), mi proyecto más importante para ayudarte a estudiar programación y desarrollo de software de manera diferente. + +> **¿Buscas un extra?** Aquí encontrarás este y otros cursos editados por lecciones individuales, para avanzar a tu ritmo y guardar el progreso. También dispondrás de ejercicios y correcciones, test para validar tus conocimientos, examen y certificado público de finalización, soporte, foro de estudiantes, reunionnes grupales, cursos exclusivos y mucho más. +> +> Entra en **[mouredev.pro](https://mouredev.pro)** y utiliza el cupón **"PYTHON"** con un 10% de descuento en tu primera suscripción. ## ![https://mouredev.com](https://raw.githubusercontent.com/mouredev/mouredev/master/mouredev_emote.png) Hola, mi nombre es Brais Moure. + ### Freelance full-stack iOS & Android engineer [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCxPD7bsocoAMq8Dj18kmGyQ?style=social)](https://youtube.com/mouredevapps?sub_confirmation=1) @@ -180,6 +180,8 @@ Si quieres unirte a nuestra comunidad de desarrollo, aprender programación de A Soy ingeniero de software desde 2010. Desde 2018 combino mi trabajo desarrollando Apps con la creación de contenido formativo sobre programación y tecnología en diferentes redes sociales como **[@mouredev](https://moure.dev)**. -### En mi perfil de GitHub tienes más información +Si quieres unirte a nuestra comunidad de desarrollo, aprender programación, mejorar tus habilidades y ayudar a la continuidad del proyecto, puedes encontrarnos en: -[![Web](https://img.shields.io/badge/GitHub-MoureDev-14a1f0?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/mouredev) +[![Twitch](https://img.shields.io/badge/Twitch-Programación_en_directo-9146FF?style=for-the-badge&logo=twitch&logoColor=white&labelColor=101010)](https://twitch.tv/mouredev) +[![Discord](https://img.shields.io/badge/Discord-Servidor_de_la_comunidad-5865F2?style=for-the-badge&logo=discord&logoColor=white&labelColor=101010)](https://mouredev.com/discord) [![Pro](https://img.shields.io/badge/Cursos-mouredev.pro-FF5500?style=for-the-badge&logo=gnometerminal&logoColor=white&labelColor=101010)](https://moure.dev) +[![Link](https://img.shields.io/badge/Links_de_interés-moure.dev-14a1f0?style=for-the-badge&logo=Linktree&logoColor=white&labelColor=101010)](https://moure.dev) [![Web](https://img.shields.io/badge/GitHub-MoureDev-087ec4?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/mouredev)