├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── db.py ├── game_controller.py └── main.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # celery beat schedule file 95 | celerybeat-schedule 96 | 97 | # SageMath parsed files 98 | *.sage.py 99 | 100 | # Environments 101 | .env 102 | .venv 103 | env/ 104 | venv/ 105 | ENV/ 106 | env.bak/ 107 | venv.bak/ 108 | 109 | # Spyder project settings 110 | .spyderproject 111 | .spyproject 112 | 113 | # Rope project settings 114 | .ropeproject 115 | 116 | # mkdocs documentation 117 | /site 118 | 119 | # mypy 120 | .mypy_cache/ 121 | .dmypy.json 122 | dmypy.json 123 | 124 | # Pyre type checker 125 | .pyre/ 126 | 127 | # La base de datos 128 | games.db -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Luis Cabrera Benito 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # API REST usando Flask, Python, SQLite3 y JSON 2 | Ejemplo de una API creada con Python usando el micro framework de Flask y la base de datos SQLite3. 3 | La API se puede consumir con cualquier lenguaje de programación que soporte peticiones HTTP o usando Postman: 4 | 5 | ![Consumiendo API REST creada con Flask y Python usando SQLite 3 y JSON - By Parzibyte](https://parzibyte.me/blog/wp-content/uploads/2020/11/Consumiendo-API-REST-creada-con-Flask-y-Python-usando-SQLite-y-JSON.png) 6 | 7 | 8 | Si te gusta Python, te invito a leer [más contenido de ese tema en mi blog](https://parzibyte.me/blog/category/python/). 9 | 10 | **By Parzibyte** (https://parzibyte.me/blog) 11 | 12 | # Explicación 13 | Mira la explicación del código en mi blog: https://parzibyte.me/blog/2020/11/10/api-rest-python-flask-sqlite3/ 14 | 15 | # Demostración 16 | También puedes probar la API en línea, en el siguiente enlace (revisa las rutas definidas en caso de que aparezca un error 404): [https://apirestflaskpythonsqlite3.parzibyte.repl.co/](https://apirestflaskpythonsqlite3.parzibyte.repl.co/) 17 | 18 | Por ejemplo, para ver todos los juegos, es: [https://apirestflaskpythonsqlite3.parzibyte.repl.co/games](https://apirestflaskpythonsqlite3.parzibyte.repl.co/games) 19 | -------------------------------------------------------------------------------- /db.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | ____ _____ _ _ _ 4 | | _ \ | __ \ (_) | | | 5 | | |_) |_ _ | |__) |_ _ _ __ _____| |__ _ _| |_ ___ 6 | | _ <| | | | | ___/ _` | '__|_ / | '_ \| | | | __/ _ \ 7 | | |_) | |_| | | | | (_| | | / /| | |_) | |_| | || __/ 8 | |____/ \__, | |_| \__,_|_| /___|_|_.__/ \__, |\__\___| 9 | __/ | __/ | 10 | |___/ |___/ 11 | 12 | ____________________________________ 13 | / Si necesitas ayuda, contáctame en \ 14 | \ https://parzibyte.me / 15 | ------------------------------------ 16 | \ ^__^ 17 | \ (oo)\_______ 18 | (__)\ )\/\ 19 | ||----w | 20 | || || 21 | Creado por Parzibyte (https://parzibyte.me). Este encabezado debe mantenerse intacto, 22 | excepto si este es un proyecto de un estudiante. 23 | """ 24 | import sqlite3 25 | DATABASE_NAME = "games.db" 26 | 27 | 28 | def get_db(): 29 | conn = sqlite3.connect(DATABASE_NAME) 30 | return conn 31 | 32 | 33 | def create_tables(): 34 | tables = [ 35 | """CREATE TABLE IF NOT EXISTS games( 36 | id INTEGER PRIMARY KEY AUTOINCREMENT, 37 | name TEXT NOT NULL, 38 | price REAL NOT NULL, 39 | rate INTEGER NOT NULL 40 | ) 41 | """ 42 | ] 43 | db = get_db() 44 | cursor = db.cursor() 45 | for table in tables: 46 | cursor.execute(table) 47 | -------------------------------------------------------------------------------- /game_controller.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | ____ _____ _ _ _ 4 | | _ \ | __ \ (_) | | | 5 | | |_) |_ _ | |__) |_ _ _ __ _____| |__ _ _| |_ ___ 6 | | _ <| | | | | ___/ _` | '__|_ / | '_ \| | | | __/ _ \ 7 | | |_) | |_| | | | | (_| | | / /| | |_) | |_| | || __/ 8 | |____/ \__, | |_| \__,_|_| /___|_|_.__/ \__, |\__\___| 9 | __/ | __/ | 10 | |___/ |___/ 11 | 12 | ____________________________________ 13 | / Si necesitas ayuda, contáctame en \ 14 | \ https://parzibyte.me / 15 | ------------------------------------ 16 | \ ^__^ 17 | \ (oo)\_______ 18 | (__)\ )\/\ 19 | ||----w | 20 | || || 21 | Creado por Parzibyte (https://parzibyte.me). Este encabezado debe mantenerse intacto, 22 | excepto si este es un proyecto de un estudiante. 23 | """ 24 | from db import get_db 25 | 26 | 27 | def insert_game(name, price, rate): 28 | db = get_db() 29 | cursor = db.cursor() 30 | statement = "INSERT INTO games(name, price, rate) VALUES (?, ?, ?)" 31 | cursor.execute(statement, [name, price, rate]) 32 | db.commit() 33 | return True 34 | 35 | 36 | def update_game(id, name, price, rate): 37 | db = get_db() 38 | cursor = db.cursor() 39 | statement = "UPDATE games SET name = ?, price = ?, rate = ? WHERE id = ?" 40 | cursor.execute(statement, [name, price, rate, id]) 41 | db.commit() 42 | return True 43 | 44 | 45 | def delete_game(id): 46 | db = get_db() 47 | cursor = db.cursor() 48 | statement = "DELETE FROM games WHERE id = ?" 49 | cursor.execute(statement, [id]) 50 | db.commit() 51 | return True 52 | 53 | 54 | def get_by_id(id): 55 | db = get_db() 56 | cursor = db.cursor() 57 | statement = "SELECT id, name, price, rate FROM games WHERE id = ?" 58 | cursor.execute(statement, [id]) 59 | return cursor.fetchone() 60 | 61 | 62 | def get_games(): 63 | db = get_db() 64 | cursor = db.cursor() 65 | query = "SELECT id, name, price, rate FROM games" 66 | cursor.execute(query) 67 | return cursor.fetchall() 68 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | ____ _____ _ _ _ 4 | | _ \ | __ \ (_) | | | 5 | | |_) |_ _ | |__) |_ _ _ __ _____| |__ _ _| |_ ___ 6 | | _ <| | | | | ___/ _` | '__|_ / | '_ \| | | | __/ _ \ 7 | | |_) | |_| | | | | (_| | | / /| | |_) | |_| | || __/ 8 | |____/ \__, | |_| \__,_|_| /___|_|_.__/ \__, |\__\___| 9 | __/ | __/ | 10 | |___/ |___/ 11 | 12 | ____________________________________ 13 | / Si necesitas ayuda, contáctame en \ 14 | \ https://parzibyte.me / 15 | ------------------------------------ 16 | \ ^__^ 17 | \ (oo)\_______ 18 | (__)\ )\/\ 19 | ||----w | 20 | || || 21 | Creado por Parzibyte (https://parzibyte.me). Este encabezado debe mantenerse intacto, 22 | excepto si este es un proyecto de un estudiante. 23 | """ 24 | """ 25 | API REST con Python 3 y SQLite 3 26 | By Parzibyte: 27 | ** https://parzibyte.me/blog ** 28 | """ 29 | from flask import Flask, jsonify, request 30 | import game_controller 31 | from db import create_tables 32 | 33 | app = Flask(__name__) 34 | 35 | 36 | @app.route('/games', methods=["GET"]) 37 | def get_games(): 38 | games = game_controller.get_games() 39 | return jsonify(games) 40 | 41 | 42 | @app.route("/game", methods=["POST"]) 43 | def insert_game(): 44 | game_details = request.get_json() 45 | name = game_details["name"] 46 | price = game_details["price"] 47 | rate = game_details["rate"] 48 | result = game_controller.insert_game(name, price, rate) 49 | return jsonify(result) 50 | 51 | 52 | @app.route("/game", methods=["PUT"]) 53 | def update_game(): 54 | game_details = request.get_json() 55 | id = game_details["id"] 56 | name = game_details["name"] 57 | price = game_details["price"] 58 | rate = game_details["rate"] 59 | result = game_controller.update_game(id, name, price, rate) 60 | return jsonify(result) 61 | 62 | 63 | @app.route("/game/", methods=["DELETE"]) 64 | def delete_game(id): 65 | result = game_controller.delete_game(id) 66 | return jsonify(result) 67 | 68 | 69 | @app.route("/game/", methods=["GET"]) 70 | def get_game_by_id(id): 71 | game = game_controller.get_by_id(id) 72 | return jsonify(game) 73 | 74 | """ 75 | Enable CORS. Disable it if you don't need CORS 76 | """ 77 | @app.after_request 78 | def after_request(response): 79 | response.headers["Access-Control-Allow-Origin"] = "*" # <- You can change "*" for a domain for example "http://localhost" 80 | response.headers["Access-Control-Allow-Credentials"] = "true" 81 | response.headers["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS, PUT, DELETE" 82 | response.headers["Access-Control-Allow-Headers"] = "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization" 83 | return response 84 | 85 | 86 | if __name__ == "__main__": 87 | create_tables() 88 | """ 89 | Here you can change debug and port 90 | Remember that, in order to make this API functional, you must set debug in False 91 | """ 92 | app.run(host='0.0.0.0', port=8000, debug=False) 93 | --------------------------------------------------------------------------------