diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..029519e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.py[cod] \ No newline at end of file diff --git a/Backend/FastAPI/__pycache__/main.cpython-310.pyc b/Backend/FastAPI/__pycache__/main.cpython-310.pyc deleted file mode 100644 index a6b2a3a3..00000000 Binary files a/Backend/FastAPI/__pycache__/main.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/__pycache__/products.cpython-310.pyc b/Backend/FastAPI/__pycache__/products.cpython-310.pyc deleted file mode 100644 index 3dc8d32d..00000000 Binary files a/Backend/FastAPI/__pycache__/products.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/__pycache__/users.cpython-310.pyc b/Backend/FastAPI/__pycache__/users.cpython-310.pyc deleted file mode 100644 index 0d94f03f..00000000 Binary files a/Backend/FastAPI/__pycache__/users.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/db/__pycache__/client.cpython-310.pyc b/Backend/FastAPI/db/__pycache__/client.cpython-310.pyc deleted file mode 100644 index 23a66f17..00000000 Binary files a/Backend/FastAPI/db/__pycache__/client.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/db/client.py b/Backend/FastAPI/db/client.py index 498e15f1..d92a3616 100644 --- a/Backend/FastAPI/db/client.py +++ b/Backend/FastAPI/db/client.py @@ -1,4 +1,4 @@ -# Clase en vídeo (22/12/2022): https://www.twitch.tv/videos/1686104006 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480) ### MongoDB client ### @@ -10,4 +10,22 @@ from pymongo import MongoClient -db_client = MongoClient() +# Descomentar el db_client local o remoto correspondiente + +# Base de datos local MongoDB +db_client = MongoClient().local + +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=25470 + +# Base de datos remota MongoDB Atlas (https://mongodb.com) +# db_client = MongoClient( +# "mongodb+srv://:@/?retryWrites=true&w=majority").test + +# Despliegue API en la nube: +# 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/__pycache__/user.cpython-310.pyc b/Backend/FastAPI/db/models/__pycache__/user.cpython-310.pyc deleted file mode 100644 index 22edbcd1..00000000 Binary files a/Backend/FastAPI/db/models/__pycache__/user.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/db/models/user.py b/Backend/FastAPI/db/models/user.py index 75446ad2..73d57665 100644 --- a/Backend/FastAPI/db/models/user.py +++ b/Backend/FastAPI/db/models/user.py @@ -1,11 +1,12 @@ -# Clase en vídeo (22/12/2022): https://www.twitch.tv/videos/1686104006 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480 ### User model ### from pydantic import BaseModel +from typing import Optional class User(BaseModel): - id: str | None + id: Optional[str] = None username: str email: str diff --git a/Backend/FastAPI/db/schemas/__pycache__/user.cpython-310.pyc b/Backend/FastAPI/db/schemas/__pycache__/user.cpython-310.pyc deleted file mode 100644 index 9137a545..00000000 Binary files a/Backend/FastAPI/db/schemas/__pycache__/user.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/main.py b/Backend/FastAPI/main.py index ca00e915..c8ba0830 100644 --- a/Backend/FastAPI/main.py +++ b/Backend/FastAPI/main.py @@ -1,4 +1,4 @@ -# Clase en vídeo (24/11/2022): https://www.twitch.tv/videos/1661716599 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A ### Hola Mundo ### @@ -9,19 +9,24 @@ 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() -# Routers - Clase en vídeo (08/12/2022): https://www.twitch.tv/videos/1673759045 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=12475 app.include_router(products.router) app.include_router(users.router) -# Routers - Clase en vídeo (22/12/2022): https://www.twitch.tv/videos/1686104006 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=14094 app.include_router(basic_auth_users.router) + +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=17664 app.include_router(jwt_auth_users.router) + +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480 app.include_router(users_db.router) -# Recursos estáticos - Clase en vídeo (14/12/2022): https://www.twitch.tv/videos/1679022882 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=13618 app.mount("/static", StaticFiles(directory="static"), name="static") diff --git a/Backend/FastAPI/requirements.txt b/Backend/FastAPI/requirements.txt new file mode 100644 index 00000000..8fa41bc8 --- /dev/null +++ b/Backend/FastAPI/requirements.txt @@ -0,0 +1,5 @@ +fastapi[standard] +python-jose +passlib +bcrypt +pymongo \ No newline at end of file diff --git a/Backend/FastAPI/routers/__pycache__/basic_auth_users.cpython-310.pyc b/Backend/FastAPI/routers/__pycache__/basic_auth_users.cpython-310.pyc deleted file mode 100644 index 3f26ee26..00000000 Binary files a/Backend/FastAPI/routers/__pycache__/basic_auth_users.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/routers/__pycache__/jwt_auth_users.cpython-310.pyc b/Backend/FastAPI/routers/__pycache__/jwt_auth_users.cpython-310.pyc deleted file mode 100644 index 2ffc14ac..00000000 Binary files a/Backend/FastAPI/routers/__pycache__/jwt_auth_users.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/routers/__pycache__/products.cpython-310.pyc b/Backend/FastAPI/routers/__pycache__/products.cpython-310.pyc deleted file mode 100644 index e41878c1..00000000 Binary files a/Backend/FastAPI/routers/__pycache__/products.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/routers/__pycache__/users.cpython-310.pyc b/Backend/FastAPI/routers/__pycache__/users.cpython-310.pyc deleted file mode 100644 index 17f658ee..00000000 Binary files a/Backend/FastAPI/routers/__pycache__/users.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/routers/__pycache__/users_db.cpython-310.pyc b/Backend/FastAPI/routers/__pycache__/users_db.cpython-310.pyc deleted file mode 100644 index 51e77072..00000000 Binary files a/Backend/FastAPI/routers/__pycache__/users_db.cpython-310.pyc and /dev/null differ diff --git a/Backend/FastAPI/routers/basic_auth_users.py b/Backend/FastAPI/routers/basic_auth_users.py index ad4562a9..da1b0f20 100644 --- a/Backend/FastAPI/routers/basic_auth_users.py +++ b/Backend/FastAPI/routers/basic_auth_users.py @@ -1,4 +1,4 @@ -# Clase en vídeo (14/12/2022): https://www.twitch.tv/videos/1679022882 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=14094 ### Users API con autorización OAuth2 básica ### @@ -6,7 +6,11 @@ from pydantic import BaseModel from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -router = APIRouter() +router = APIRouter( + prefix="/basicauth", + tags=["basicauth"], + responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}} +) oauth2 = OAuth2PasswordBearer(tokenUrl="login") @@ -26,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 5a599722..dd266882 100644 --- a/Backend/FastAPI/routers/jwt_auth_users.py +++ b/Backend/FastAPI/routers/jwt_auth_users.py @@ -1,4 +1,4 @@ -# Clase en vídeo (14/12/2022): https://www.twitch.tv/videos/1679022882 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=17664 ### Users API con autorización OAuth2 JWT ### @@ -7,13 +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() +router = APIRouter( + prefix="/jwtauth", + tags=["jwtauth"], + responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}} +) oauth2 = OAuth2PasswordBearer(tokenUrl="login") @@ -35,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" } @@ -88,6 +92,7 @@ async def current_user(user: User = Depends(auth_user)): @router.post("/login") async def login(form: OAuth2PasswordRequestForm = Depends()): + user_db = users_db.get(form.username) if not user_db: raise HTTPException( @@ -100,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 bebd9171..4562224c 100644 --- a/Backend/FastAPI/routers/products.py +++ b/Backend/FastAPI/routers/products.py @@ -1,15 +1,16 @@ -# Clase en vídeo (08/12/2022): https://www.twitch.tv/videos/1673759045 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=12475 ### Products API ### 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.py b/Backend/FastAPI/routers/users.py index 6ccbb198..46aca70c 100644 --- a/Backend/FastAPI/routers/users.py +++ b/Backend/FastAPI/routers/users.py @@ -1,4 +1,4 @@ -# Clase en vídeo (01/12/2022): https://www.twitch.tv/videos/1667582141 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=5382 ### Users API ### @@ -47,7 +47,7 @@ async def user(id: int): return search_user(id) -# Clase en vídeo (08/12/2022): https://www.twitch.tv/videos/1673759045 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=8529 @router.post("/user/", response_model=User, status_code=201) diff --git a/Backend/FastAPI/routers/users_db.py b/Backend/FastAPI/routers/users_db.py index ce198171..1b5645ff 100644 --- a/Backend/FastAPI/routers/users_db.py +++ b/Backend/FastAPI/routers/users_db.py @@ -1,4 +1,4 @@ -# Clase en vídeo (22/12/2022): https://www.twitch.tv/videos/1686104006 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480 ### Users DB API ### @@ -8,14 +8,15 @@ 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]) async def users(): - return users_schema(db_client.local.users.find()) + return users_schema(db_client.users.find()) @router.get("/{id}") # Path @@ -37,9 +38,9 @@ async def user(user: User): user_dict = dict(user) del user_dict["id"] - id = db_client.local.users.insert_one(user_dict).inserted_id + id = db_client.users.insert_one(user_dict).inserted_id - new_user = user_schema(db_client.local.users.find_one({"_id": id})) + new_user = user_schema(db_client.users.find_one({"_id": id})) return User(**new_user) @@ -51,7 +52,7 @@ async def user(user: User): del user_dict["id"] try: - db_client.local.users.find_one_and_replace( + db_client.users.find_one_and_replace( {"_id": ObjectId(user.id)}, user_dict) except: return {"error": "No se ha actualizado el usuario"} @@ -62,7 +63,7 @@ async def user(user: User): @router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT) async def user(id: str): - found = db_client.local.users.find_one_and_delete({"_id": ObjectId(id)}) + found = db_client.users.find_one_and_delete({"_id": ObjectId(id)}) if not found: return {"error": "No se ha eliminado el usuario"} @@ -73,7 +74,7 @@ async def user(id: str): def search_user(field: str, key): try: - user = db_client.local.users.find_one({field: key}) + user = db_client.users.find_one({field: key}) return User(**user_schema(user)) except: return {"error": "No se ha encontrado el usuario"} 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/Backend/type_hints.py b/Backend/type_hints.py index 0e9bb571..42b7c01a 100644 --- a/Backend/type_hints.py +++ b/Backend/type_hints.py @@ -1,4 +1,4 @@ -# Clase en vídeo (24/11/2022): https://www.twitch.tv/videos/1661716599 +# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=1810 ### Type Hints ### 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/header.jpg b/Images/header.jpg new file mode 100644 index 00000000..c5522ddb Binary files /dev/null and b/Images/header.jpg differ 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/Intermediate/mypackage/__pycache__/__init__.cpython-310.pyc b/Intermediate/mypackage/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index e2206973..00000000 Binary files a/Intermediate/mypackage/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/Intermediate/mypackage/__pycache__/arithmetics.cpython-310.pyc b/Intermediate/mypackage/__pycache__/arithmetics.cpython-310.pyc deleted file mode 100644 index 6e2cf799..00000000 Binary files a/Intermediate/mypackage/__pycache__/arithmetics.cpython-310.pyc and /dev/null differ diff --git a/README.md b/README.md index b1688d07..c423682a 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,21 @@ # Hello Python -[![Python](https://img.shields.io/badge/Python-3.9+-yellow?style=for-the-badge&logo=python&logoColor=white&labelColor=101010)](https://python.org) +[![Python](https://img.shields.io/badge/Python-3.10+-yellow?style=for-the-badge&logo=python&logoColor=white&labelColor=101010)](https://python.org) +[![FastAPI](https://img.shields.io/badge/FastAPI-0.88.0+-00a393?style=for-the-badge&logo=fastapi&logoColor=white&labelColor=101010)](https://fastapi.tiangolo.com) +[![MongoDB](https://img.shields.io/badge/MongoDB-6.0+-00684A?style=for-the-badge&logo=mongodb&logoColor=white&labelColor=101010)](https://www.mongodb.com) +[![ChatGPT](https://img.shields.io/badge/ChatGPT-GPT--4-7CF178?style=for-the-badge&logo=openai&logoColor=white&labelColor=101010)](https://platform.openai.com) +[![Reflex](https://img.shields.io/badge/Reflex-0.4.6+-5646ED?style=for-the-badge&logo=reflex&logoColor=white&labelColor=101010)](https://reflex.dev) ## Curso para aprender el lenguaje de programación Python desde cero y para principiantes -### Proyecto realizado durante emisiones en directo desde [Twitch](https://twitch.tv/mouredev) - -### 🐍 CADA SEMANA UNA NUEVA CLASE EN DIRECTO 🐍 -##### Si consideras útil esta actividad, apóyala haciendo "★ Star" en el repositorio. ¡Gracias! +![](./Images/header.jpg) -> --- -> Estoy llevando a cabo un CURSO DESDE CERO gratis para aprender PYTHON en BACKEND. -> -> **🔴 SIGUIENTE CLASE: Miércoles 28 de Diciembre a las 20:00 (hora España)** +### Proyecto realizado durante emisiones en directo desde [Twitch](https://twitch.tv/mouredev) -> 🗓 En [Discord](https://discord.gg/mouredev) tienes creado un [evento](https://discord.gg/mouredev?event=1055759221637009508) para que consultes la hora de tu país y añadas un recordatorio. -> -> Mientras, aprovecha para practicar unos [retos de programación](https://retosdeprogramacion.com/semanales2022) y así ir mejorando poco a poco. -> -> *Finalizada la clase, se actualizará el repositorio con los nuevos recursos* -> -> --- +> ##### Si consideras útil el curso, apóyalo haciendo "★ Star" en el repositorio. ¡Gracias! ## Clases en vídeo -### [EN CURSO] Backend desde cero - -Curso en el que aprenderemos a utilizar Python para backend e implementaremos un API REST con autenticación, base de datos y desplegaremos el proyecto en un servidor real. - -> Código: Directorio "Backend" en el proyecto - -* [Clase 1 - 24/11/2022 - Hola Mundo en FastAPI](https://www.twitch.tv/videos/1661716599) -* [Clase 2 - 01/12/2022 - Operaciones con GET y peticiones HTTP](https://www.twitch.tv/videos/1667582141) -* [Clase 3 - 08/12/2022 - Operaciones con POST, PUT, DELETE, códigos HTTP y Routers](https://www.twitch.tv/videos/1673759045) -* [Clase 4 - 14/12/2022 - Recursos estáticos y Autorización OAuth2](https://www.twitch.tv/videos/1679022882) -* [Clase 5 - 22/12/2022 - Base de datos con MongoDB](https://www.twitch.tv/videos/1686104006) - ### Curso de fundamentos desde cero Curso que agrupa todas las clases en directo que hacen referencia a los fundamentos de Python. @@ -44,93 +24,151 @@ 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) -## Información importante y preguntas frecuentes +### Backend desde cero -* **¿Cómo está estructurado el proyecto y el código?** - * Actualmente tienes tres directorios, "Basic", "Intermediate" y "Backend", correspondientes a cómo están agrupados los cursos. +Curso en el que aprenderemos a utilizar Python para backend e implementaremos un API REST con autenticación, base de datos y desplegaremos el proyecto en un servidor real. -* **¿Las clases nuevas quedan grabadas?** - * Todos los directos de Twitch están disponibles 60 días en la sección [vídeos](https://twitch.tv/mouredev/videos). +> Código: Directorio "Backend" en el proyecto -* **¿Puedo asistir a las clases en directo si no he visto las anteriores?** - * Sí. Son clases independientes en las que hablo de nuevo de conceptos anteriores para que se entiendan de nuevo. Por supuesto, es recomendable que poco a poco visualices las clases anteriores. + -* **¿Se subirá a YouTube?** - * No te preocupes, antes de que se cumplan los 60 días de Twitch, iré publicando las clases agrupadas en YouTube. +- [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) -* **¿Harás un curso?** - * Agruparé lecciones en YouTube para crear cursos por nivel. Actualmente ya existe el de [fundamentos desde cero](https://youtu.be/Kp4Mvapo5kc) e [intermedio](https://youtu.be/TbcEqkabAWU). +**\*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). -* **¿Hasta dónde llegará el curso?** - * Mi idea es repasar los conceptos básicos hasta llegar a crear un backend (en principio). +### Frontend desde cero -* **¿Cuándo será la próxima clase?** - * Te recomiendo que me sigas en redes, sobre todo en [Discord](https://discord.gg/mouredev) e [Instagram](https://instagram.com/mouredev) donde creo eventos a diario con la hora de emisión (así podrás ver qué hora es en tu país). - * También he creado en el Discord un canal "🐍curso-python" para que puedas comentar lo que quieras. - * Una vez finalizada la clase subiré los ficheros de código a este repositorio. +Cursos en los que aprenderemos a utilizar Python para desarrollo web con dos proyectos reales desplegados en producción. Tutoriales en vídeo paso a paso con 9 horas de contenido. ---- + -### 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 + ---- +[![Curso Python Web](https://img.shields.io/github/stars/mouredev/python-web?label=Curso%20Python%20web&style=social)](https://github.com/mouredev/python-web) -#### Puedes apoyar mi trabajo haciendo "☆ Star" en el repo o nominarme a "GitHub Star". ¡Gracias! + -[![GitHub Star](https://img.shields.io/badge/GitHub-Nominar_a_star-yellow?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://stars.github.com/nominate/) +[![Curso Python Web](https://img.shields.io/github/stars/mouredev/adeviento-web?label=Tutorial%20Python%20web%20extra&style=social)](https://github.com/mouredev/adeviento-web) -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: +### Aprende a integrar ChatGPT en tu proyecto desde cero -[![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) + + +Clase de una hora de duración donde aprenderás a interactuar con ChatGPT desde tu aplicación, mantener conversaciones y establecer el contexto de la IA para potenciar tu proyecto. + +Con todo el código publicado [aquí](https://gist.github.com/mouredev/58abfbcef017efaf3852e8821564c011). + +### Traductor de Voz con IA + + + +Aprende a desarrollar un traductor de voz a varios idiomas utilizando con IA. Creando su Web y todo en 100 líneas. + +Con todo el código publicado [aquí](https://gist.github.com/mouredev/0ea42112751f0187d90d5403d1f333e2). + +### Introducción al Testing + +Taller de introducción a testing con Python creado junto a [Carlos Blé](https://www.carlosble.com) y [Miguel A. Gómez](https://softwarecrafters.io), expertos en la materia. + + + +### Extra: 15 curiosidades sobre Python + +Y para finalizar... ¿Quieres saber aun más sobre él? Aquí tienes 15 curiosidades que quizás no conozcas sobre el lenguaje. + + + +## Información importante y preguntas frecuentes + +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. + +¡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 +- [Vercel](https://vercel.com/): Para desplegar nuestra API en la nube + +## Únete al campus de programación de la comunidad + +![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) @@ -140,8 +178,10 @@ Si quieres unirte a nuestra comunidad de desarrollo, aprender programación de A ![GitHub Followers](https://img.shields.io/github/followers/mouredev?style=social) ![GitHub Followers](https://img.shields.io/github/stars/mouredev?style=social) -Soy ingeniero de software desde hace más de 12 años. Desde hace 4 años combino mi trabajo desarrollando Apps con creación de contenido formativo sobre programación y tecnología en diferentes redes sociales como **[@mouredev](https://moure.dev)**. +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) diff --git a/__pycache__/module.cpython-310.pyc b/__pycache__/module.cpython-310.pyc deleted file mode 100644 index 0d63bb63..00000000 Binary files a/__pycache__/module.cpython-310.pyc and /dev/null differ diff --git a/__pycache__/my_module.cpython-310.pyc b/__pycache__/my_module.cpython-310.pyc deleted file mode 100644 index ca5d74d7..00000000 Binary files a/__pycache__/my_module.cpython-310.pyc and /dev/null differ