Skip to content

Dela Cruz Glenn Paul Bryan #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 116 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,116 @@
# Example Python Flask Crud

Simple example python flask crud app for sqlite.

## Screenshots


![image](screenshots.png)


### Installing (for linux)

open the terminal and follow the white rabbit.


```
git clone https://github.com/gurkanakdeniz/example-flask-crud.git
```
```
cd example-flask-crud/
```
```
python3 -m venv venv
```
```
source venv/bin/activate
```
```
pip install --upgrade pip
```
```
pip install -r requirements.txt
```
```
export FLASK_APP=crudapp.py
```
```
flask db init
```
```
flask db migrate -m "entries table"
```
```
flask db upgrade
```
```
flask run
```

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
# Flask CRUD Example with Authors API

## Project Overview

This is a simple Flask web application demonstrating CRUD (Create, Read, Update, Delete) REST API functionality for managing entries and authors.
It uses Flask, SQLAlchemy for ORM, and Flask-Migrate for database migrations.
Swagger UI is integrated for interactive API documentation.

---

## Features

- CRUD operations for `Entry` model (title, description, status)
- CRUD REST API for `Author` model (name, bio) implemented using Flask Blueprint
- RESTful API endpoints with JSON request/response format and proper HTTP status codes
- Swagger UI documentation available at `/docs`
- Unit tests covering all API functionality using `pytest`

---

## Installation

1. Clone the repository:
```bash
git clone https://github.com/gurkanakdeniz/example-flask-crud.git
cd example-flask-crud


2. Create a virtual environment and activate it:

python -m venv iptvenv
iptvenv\Scripts\activate

3. Install dependencies:

pip install -r requirements.txt

4. Initialize the database:
(You only need to run flask db init once if not done before)

flask db init
flask db migrate -m "Add Author model"
flask db upgrade


5. Run the application:

python crudapp.py

---

## Usage
1. Access the main page for managing entries:
http://localhost:5000

2. Access authors UI:
http://localhost:5000/authors_ui

3. REST API endpoints are documented and available via Swagger UI:
http://localhost:5000/docs

REST API Endpoints for Author
Method Endpoint Description
GET /authors List all authors
POST /authors Create new author
GET /authors/<id> Get author by ID
PUT /authors/<id> Update author by ID
DELETE /authors/<id> Delete author by ID

---

## API Documentation
1. Interactive API documentation is available via Swagger UI at:
http://localhost:5000/docs

(If flask-swagger-ui is not installed, install it using:)

pip install flask-swagger-ui

---

## Testing
1. If pytest is not installed, install it:

pip install pytest

2. Run tests with:

pytest test_author_api.py

---

## Changes I Made

1. I added a new feature: the Author Management API.

2. I created a new `Author` model with fields `name` and `bio` in `models.py`, and added a `to_dict()` method to help serialize author data to JSON.

3. I implemented a RESTful API for the Author model using a Flask Blueprint in `author_routes.py`.

4. I developed full CRUD functionality with JSON request and response formats, making sure to use proper HTTP status codes.

5. I registered the Author blueprint in the app’s `__init__.py` file.

6. I integrated Swagger UI for API documentation by adding an OpenAPI-compliant `swagger.json` under the static folder and configured it to serve at the `/docs` endpoint.

7. I wrote unit tests in `test_author_api.py` to cover all CRUD operations, including both positive and negative test cases, and achieved full test coverage using `pytest`.

8. I added a simple HTML UI for authors accessible at `/authors_ui` as an optional enhancement.

9. Finally, I updated `requirements.txt` to include `flask-swagger-ui` and `pytest`.

---

## Passed by: Glenn Paul Bryan Dela Cruz
## IPT Final Hands on activity
18 changes: 17 additions & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,25 @@
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)
app = Flask(__name__) # No need to set static_folder now
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)

from app import routes, models
from app.author_routes import author_bp
app.register_blueprint(author_bp)

# Swagger UI
from flask_swagger_ui import get_swaggerui_blueprint

SWAGGER_URL = '/docs'
API_URL = '/static/swagger.json'

swaggerui_blueprint = get_swaggerui_blueprint(
SWAGGER_URL, API_URL, config={'app_name': "Author API"}
)
app.register_blueprint(swaggerui_blueprint, url_prefix=SWAGGER_URL)



58 changes: 58 additions & 0 deletions app/author_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from flask import Blueprint, request, jsonify
from app import db
from app.models import Author

author_bp = Blueprint('authors', __name__, url_prefix='/authors')

# Create
@author_bp.route('', methods=['POST'])
def create_author():
data = request.get_json()
name = data.get('name')
bio = data.get('bio')

if not name:
return jsonify({"error": "Name is required"}), 400

new_author = Author(name=name, bio=bio)
db.session.add(new_author)
db.session.commit()
return jsonify(new_author.to_dict()), 201

# Read All
@author_bp.route('', methods=['GET'])
def get_authors():
authors = Author.query.all()
return jsonify([a.to_dict() for a in authors]), 200

# Read One by ID
@author_bp.route('/<int:id>', methods=['GET'])
def get_author(id):
author = Author.query.get(id)
if not author:
return jsonify({"error": "Author not found"}), 404
return jsonify(author.to_dict()), 200

# Update
@author_bp.route('/<int:id>', methods=['PUT'])
def update_author(id):
author = Author.query.get(id)
if not author:
return jsonify({"error": "Author not found"}), 404

data = request.get_json()
author.name = data.get('name', author.name)
author.bio = data.get('bio', author.bio)
db.session.commit()
return jsonify(author.to_dict()), 200

# Delete
@author_bp.route('/<int:id>', methods=['DELETE'])
def delete_author(id):
author = Author.query.get(id)
if not author:
return jsonify({"error": "Author not found"}), 404

db.session.delete(author)
db.session.commit()
return jsonify({"message": "Author deleted"}), 200
14 changes: 13 additions & 1 deletion app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,16 @@ class Entry(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(64), index=True, nullable=False)
description = db.Column(db.String(120), index=True, nullable=False)
status = db.Column(db.Boolean, default=False)
status = db.Column(db.Boolean, default=False)

class Author(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
bio = db.Column(db.Text)

def to_dict(self):
return {
"id": self.id,
"name": self.name,
"bio": self.bio
}
10 changes: 9 additions & 1 deletion app/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,12 @@ def turn(id):

# @app.errorhandler(Exception)
# def error_page(e):
# return "of the jedi"
# return "of the jedi"

from flask import render_template



@app.route('/authors_ui')
def authors_ui():
return render_template('authors.html')
Loading