Skip to content

Commit 140c04d

Browse files
committed
add building crud app with flask tutorial
1 parent 16a7329 commit 140c04d

File tree

8 files changed

+155
-2
lines changed

8 files changed

+155
-2
lines changed

README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,6 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
100100
- [How to Get the Size of Directories in Python](https://www.thepythoncode.com/article/get-directory-size-in-bytes-using-python). ([code](general/calculate-directory-size))
101101
- [How to Get Geographic Locations in Python](https://www.thepythoncode.com/article/get-geolocation-in-python). ([code](general/geolocation))
102102
- [How to Assembly, Disassembly and Emulate Machine Code using Python](https://www.thepythoncode.com/article/arm-x86-64-assembly-disassembly-and-emulation-in-python). ([code](general/assembly-code))
103-
- [Detecting Fraudulent Transactions in a Streaming Application using Kafka in Python](https://www.thepythoncode.com/article/detect-fraudulent-transactions-with-apache-kafka-in-python). ([code](general/detect-fraudulent-transactions))
104-
- [Asynchronous Tasks with Celery in Python](https://www.thepythoncode.com/article/async-tasks-with-celery-redis-and-flask-in-python). ([code](https://github.com/bassemmarji/flask_sync_async))
105103
- [How to Change Text Color in Python](https://www.thepythoncode.com/article/change-text-color-in-python). ([code](general/printing-in-colors))
106104
- [How to Create a Watchdog in Python](https://www.thepythoncode.com/article/create-a-watchdog-in-python). ([code](general/directory-watcher))
107105
- [How to Convert Pandas Dataframes to HTML Tables in Python](https://www.thepythoncode.com/article/convert-pandas-dataframe-to-html-table-python). ([code](general/dataframe-to-html))
@@ -199,4 +197,9 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
199197
- [How to Add Audio to Video in Python](https://www.thepythoncode.com/article/add-audio-to-video-in-python). ([code](python-for-multimedia/add-audio-to-video))
200198
- [How to Compress Images in Python](https://www.thepythoncode.com/article/compress-images-in-python). ([code](python-for-multimedia/compress-image))
201199

200+
- ### [Web Programming]()
201+
- [Detecting Fraudulent Transactions in a Streaming Application using Kafka in Python](https://www.thepythoncode.com/article/detect-fraudulent-transactions-with-apache-kafka-in-python). ([code](general/detect-fraudulent-transactions))
202+
- [Asynchronous Tasks with Celery in Python](https://www.thepythoncode.com/article/async-tasks-with-celery-redis-and-flask-in-python). ([code](https://github.com/bassemmarji/flask_sync_async))
203+
- [How to Build a CRUD App with Flask and SQLAlchemy in Python](https://www.thepythoncode.com/article/building-crud-app-with-flask-and-sqlalchemy). ([code](web-programming/bookshop-crud-app-flask))
204+
202205
For any feedback, please consider pulling requests.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2022 Ezzeddin Abdullah
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
this software and associated documentation files (the "Software"), to deal in
7+
the Software without restriction, including without limitation the rights to
8+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+
the Software, and to permit persons to whom the Software is furnished to do so,
10+
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, FITNESS
17+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# [How to Build a CRUD App with Flask and SQLAlchemy in Python](https://www.thepythoncode.com/article/building-crud-app-with-flask-and-sqlalchemy)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from flask import Flask
2+
from flask_sqlalchemy import SQLAlchemy
3+
from config import config
4+
5+
db = SQLAlchemy()
6+
7+
8+
def create_app(config_name):
9+
app = Flask(__name__)
10+
app.config.from_object(config[config_name])
11+
config[config_name].init_app(app)
12+
13+
db.init_app(app)
14+
return app
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from . import db
2+
3+
4+
class Book(db.Model):
5+
__tablename__ = 'books'
6+
isbn = db.Column(db.Integer, primary_key=True)
7+
author = db.Column(db.String(100), nullable=False)
8+
title = db.Column(db.String(100), nullable=False)
9+
price = db.Column(db.Float)
10+
11+
def to_json(self):
12+
return {
13+
'isbn': self.isbn,
14+
'author': self.author,
15+
'title': self.title,
16+
'price': self.price
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import os
2+
from . import create_app
3+
from .models import Book
4+
from . import db
5+
from flask import jsonify, request, abort
6+
7+
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
8+
9+
10+
@app.route("/book/list", methods=["GET"])
11+
def get_books():
12+
books = Book.query.all()
13+
return jsonify([book.to_json() for book in books])
14+
15+
16+
@app.route("/book/<int:isbn>", methods=["GET"])
17+
def get_book(isbn):
18+
book = Book.query.get(isbn)
19+
if book is None:
20+
abort(404)
21+
return jsonify(book.to_json())
22+
23+
24+
@app.route("/book/<int:isbn>", methods=["DELETE"])
25+
def delete_book(isbn):
26+
book = Book.query.get(isbn)
27+
if book is None:
28+
abort(404)
29+
db.session.delete(book)
30+
db.session.commit()
31+
return jsonify({'result': True})
32+
33+
34+
@app.route('/book', methods=['POST'])
35+
def create_book():
36+
if not request.json:
37+
abort(400)
38+
book = Book(
39+
title=request.json.get('title'),
40+
author=request.json.get('author'),
41+
price=request.json.get('price')
42+
)
43+
db.session.add(book)
44+
db.session.commit()
45+
return jsonify(book.to_json()), 201
46+
47+
48+
@app.route('/book/<int:isbn>', methods=['PUT'])
49+
def update_book(isbn):
50+
if not request.json:
51+
abort(400)
52+
book = Book.query.get(isbn)
53+
if book is None:
54+
abort(404)
55+
book.title = request.json.get('title', book.title)
56+
book.author = request.json.get('author', book.author)
57+
book.price = request.json.get('price', book.price)
58+
db.session.commit()
59+
return jsonify(book.to_json())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from app import db
2+
from app.routes import app
3+
from app.models import Book
4+
5+
6+
@app.shell_context_processor
7+
def make_shell_context():
8+
return dict(db=db, Book=Book)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import os
2+
3+
4+
class Config:
5+
SQLALCHEMY_TRACK_MODIFICATIONS = False
6+
7+
@staticmethod
8+
def init_app(app):
9+
pass
10+
11+
12+
class DevelopmentConfig(Config):
13+
DEBUG = True
14+
SQLALCHEMY_DATABASE_URI = os.getenv("DEV_DATABASE_URL")
15+
16+
17+
class TestingConfig(Config):
18+
TESTING = True
19+
SQLALCHEMY_DATABASE_URI = os.getenv("TEST_DATABASE_URL")
20+
21+
22+
class ProductionConfig(Config):
23+
SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL")
24+
25+
26+
config = {
27+
'development': DevelopmentConfig,
28+
'testing': TestingConfig,
29+
'production': ProductionConfig,
30+
'default': DevelopmentConfig
31+
}

0 commit comments

Comments
 (0)