here is the full template for a flask app
This commit is contained in:
parent
8fddbed915
commit
d97d90c0ea
11 changed files with 250 additions and 0 deletions
4
.env.example
Normal file
4
.env.example
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
FLASK_APP=main.py
|
||||||
|
FLASK_ENV=development
|
||||||
|
SECRET_KEY=change-this-to-a-random-secret-key
|
||||||
|
DATABASE_URL=sqlite:///app.db
|
||||||
65
README.md
Normal file
65
README.md
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Flask Base Application
|
||||||
|
|
||||||
|
A basic Flask application with user configuration and database support.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
├── app/
|
||||||
|
│ ├── __init__.py # Application factory and extensions
|
||||||
|
│ ├── routes.py # Route definitions
|
||||||
|
│ ├── models.py # Database models
|
||||||
|
│ └── utils.py # Utility functions
|
||||||
|
├── tests/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ └── test_app.py # Unit tests
|
||||||
|
├── config.py # Configuration classes
|
||||||
|
├── main.py # Application entry point
|
||||||
|
├── requirements.txt # Python dependencies
|
||||||
|
├── .env.example # Environment variables template
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
1. **Install dependencies:**
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Configure environment:**
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# Edit .env with your own settings
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Run the application:**
|
||||||
|
```bash
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Or using Flask CLI:
|
||||||
|
```bash
|
||||||
|
flask run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The app supports multiple environments via configuration classes in `config.py`:
|
||||||
|
|
||||||
|
- **Development** (`FLASK_ENV=development`) - Default, with debug enabled
|
||||||
|
- **Testing** (`FLASK_ENV=testing`) - In-memory database, CSRF disabled
|
||||||
|
- **Production** (`FLASK_ENV=production`) - Debug disabled
|
||||||
|
|
||||||
|
## Running Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m pytest tests/
|
||||||
|
# or
|
||||||
|
python -m unittest discover tests
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
- `GET /` - Home page
|
||||||
|
- `GET /health` - Health check endpoint
|
||||||
31
app/__init__.py
Normal file
31
app/__init__.py
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
from flask import Flask
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from config import config
|
||||||
|
|
||||||
|
db = SQLAlchemy()
|
||||||
|
|
||||||
|
|
||||||
|
def create_app(config_name="default"):
|
||||||
|
"""Application factory function.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config_name: Configuration name (development, testing, production).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Configured Flask application instance.
|
||||||
|
"""
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config.from_object(config[config_name])
|
||||||
|
|
||||||
|
# Initialize extensions
|
||||||
|
db.init_app(app)
|
||||||
|
|
||||||
|
# Register blueprints
|
||||||
|
from app.routes import main as main_blueprint
|
||||||
|
app.register_blueprint(main_blueprint)
|
||||||
|
|
||||||
|
# Create database tables
|
||||||
|
with app.app_context():
|
||||||
|
db.create_all()
|
||||||
|
|
||||||
|
return app
|
||||||
19
app/models.py
Normal file
19
app/models.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
from app import db
|
||||||
|
|
||||||
|
|
||||||
|
class User(db.Model):
|
||||||
|
"""User model for the application."""
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
username = db.Column(db.String(80), unique=True, nullable=False)
|
||||||
|
email = db.Column(db.String(120), unique=True, nullable=False)
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
"""Convert user object to dictionary."""
|
||||||
|
return {
|
||||||
|
"id": self.id,
|
||||||
|
"username": self.username,
|
||||||
|
"email": self.email,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<User {self.username}>"
|
||||||
15
app/routes.py
Normal file
15
app/routes.py
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
from flask import Blueprint, jsonify, request
|
||||||
|
|
||||||
|
main = Blueprint("main", __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@main.route("/")
|
||||||
|
def index():
|
||||||
|
"""Home page route."""
|
||||||
|
return jsonify({"message": "Flask App is running"})
|
||||||
|
|
||||||
|
|
||||||
|
@main.route("/health")
|
||||||
|
def health():
|
||||||
|
"""Health check endpoint."""
|
||||||
|
return jsonify({"status": "healthy"})
|
||||||
16
app/utils.py
Normal file
16
app/utils.py
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
def format_response(data=None, message="Success", status="ok"):
|
||||||
|
"""Format a standard API response.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data: Response data payload.
|
||||||
|
message: Status message.
|
||||||
|
status: Status string (ok, error, etc.).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary with standardized response format.
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"status": status,
|
||||||
|
"message": message,
|
||||||
|
"data": data,
|
||||||
|
}
|
||||||
39
config.py
Normal file
39
config.py
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
"""Base configuration."""
|
||||||
|
SECRET_KEY = os.environ.get("SECRET_KEY", "default-secret-key")
|
||||||
|
SQLALCHEMY_DATABASE_URI = os.environ.get(
|
||||||
|
"DATABASE_URL", "sqlite:///app.db"
|
||||||
|
)
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
|
|
||||||
|
|
||||||
|
class DevelopmentConfig(Config):
|
||||||
|
"""Development configuration."""
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
|
||||||
|
class TestingConfig(Config):
|
||||||
|
"""Testing configuration."""
|
||||||
|
TESTING = True
|
||||||
|
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
|
||||||
|
WTF_CSRFS_ENABLED = False
|
||||||
|
|
||||||
|
|
||||||
|
class ProductionConfig(Config):
|
||||||
|
"""Production configuration."""
|
||||||
|
DEBUG = False
|
||||||
|
TESTING = False
|
||||||
|
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"development": DevelopmentConfig,
|
||||||
|
"testing": TestingConfig,
|
||||||
|
"production": ProductionConfig,
|
||||||
|
"default": DevelopmentConfig,
|
||||||
|
}
|
||||||
9
main.py
Normal file
9
main.py
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import os
|
||||||
|
from app import create_app
|
||||||
|
from config import config
|
||||||
|
|
||||||
|
config_name = os.environ.get("FLASK_ENV", "development")
|
||||||
|
app = create_app(config[config_name])
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(host="0.0.0.0", port=5000, debug=True)
|
||||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Flask>=3.0.0
|
||||||
|
python-dotenv>=1.0.0
|
||||||
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
50
tests/test_app.py
Normal file
50
tests/test_app.py
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import unittest
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
from app import create_app, db
|
||||||
|
from app.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class BasicTestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
"""Set up test client and database."""
|
||||||
|
self.app = create_app("testing")
|
||||||
|
self.client = self.app.test_client()
|
||||||
|
with self.app.app_context():
|
||||||
|
db.create_all()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""Clean up database after tests."""
|
||||||
|
with self.app.app_context():
|
||||||
|
db.session.remove()
|
||||||
|
db.drop_all()
|
||||||
|
|
||||||
|
def test_index_route(self):
|
||||||
|
"""Test home page route."""
|
||||||
|
response = self.client.get("/")
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
data = response.get_json()
|
||||||
|
self.assertEqual(data["message"], "Flask App is running")
|
||||||
|
|
||||||
|
def test_health_route(self):
|
||||||
|
"""Test health check endpoint."""
|
||||||
|
response = self.client.get("/health")
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
data = response.get_json()
|
||||||
|
self.assertEqual(data["status"], "healthy")
|
||||||
|
|
||||||
|
def test_create_user(self):
|
||||||
|
"""Test creating a new user."""
|
||||||
|
with self.app.app_context():
|
||||||
|
user = User(username="testuser", email="test@example.com")
|
||||||
|
db.session.add(user)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
# Verify user was created
|
||||||
|
found_user = User.query.first()
|
||||||
|
self.assertIsNotNone(found_user)
|
||||||
|
self.assertEqual(found_user.username, "testuser")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Loading…
Add table
Reference in a new issue