tanlie il y a 6 jours
Parent
commit
026d79c122
11 fichiers modifiés avec 167 ajouts et 30 suppressions
  1. 8 8
      app/api/v1/__init__.py
  2. 3 0
      app/api/v1/book.py
  3. 13 0
      app/api/v1/goods.py
  4. 14 0
      app/api/v1/orders.py
  5. 25 8
      app/app.py
  6. 42 5
      app/config/setting.py
  7. 9 0
      app/routes/health.py
  8. 30 0
      app/utils/logger.py
  9. 5 9
      ginger.py
  10. 2 0
      requirements.txt
  11. 16 0
      tests/test_health.py

+ 8 - 8
app/api/v1/__init__.py

@@ -1,15 +1,15 @@
-"""
-__init__.py -
-auther: tanlie
-date: 2026/8/23
-"""
+"""API v1 blueprint registration."""
+
 from flask import Blueprint
 
-from app.api.v1 import user, book
+from app.api.v1 import book, goods, orders, user
 
 
 def create_blueprint_v1():
+    """Create and register all v1 API blueprints."""
     bp_v1 = Blueprint("v1", __name__)
-    user.api.register(bp_v1, url_prefix='/user')
-    book.api.register(bp_v1, url_prefix='/book')
+
+    for module in (user, book, goods, orders):
+        module.api.register(bp_v1)
+
     return bp_v1

+ 3 - 0
app/api/v1/book.py

@@ -5,7 +5,10 @@ date: 2026/8/23
 """
 
 from app.libs.Redprint import Redprint
+
 api = Redprint("book")
+
+
 @api.route('/get_book', methods=['GET'])
 def get_book():
     return '三味书屋'

+ 13 - 0
app/api/v1/goods.py

@@ -0,0 +1,13 @@
+"""
+goods -
+auther: tanlie
+date: 2026/8/23
+"""
+from app.libs.Redprint import Redprint
+
+api = Redprint("goods")
+
+
+@api.route('/get_goods', methods=['GET'])
+def get_goods():
+    return '商品信息'

+ 14 - 0
app/api/v1/orders.py

@@ -0,0 +1,14 @@
+"""
+orders -
+auther: tanlie
+date: 2026/8/23
+"""
+
+from app.libs.Redprint import Redprint
+
+api = Redprint("orders")
+
+
+@api.route('/get_order', methods=['GET'])
+def get_order():
+    return '订单信息'

+ 25 - 8
app/app.py

@@ -1,18 +1,35 @@
-"""
-app -
-auther: tanlie
-date: 2026/8/23
-"""
+"""Application factory."""
+
 from flask import Flask
 
+from app.config.setting import config
+
 
 def register_blueprints(app):
+    """Register all application blueprints."""
     from app.api.v1 import create_blueprint_v1
-    app.register_blueprint(create_blueprint_v1(),url_prefix='/v1')
+    from app.routes.health import bp as health_bp
+
+    # API v1 under /v1
+    app.register_blueprint(create_blueprint_v1(), url_prefix="/v1")
+
+    # Health endpoint at /health
+    app.register_blueprint(health_bp)
 
 
-def create_app():
+def create_app(env: str = "default"):
+    """Create and configure the Flask application."""
     app = Flask(__name__)
-    app.config.from_object('app.config.setting')
+    app.config.from_object(config[env])
+
+    # optional: initialize logging and other extensions here
+    try:
+        from app.utils.logger import setup_logging
+
+        setup_logging(app)
+    except Exception:
+        # keep app creation robust even if logging setup fails
+        pass
+
     register_blueprints(app)
     return app

+ 42 - 5
app/config/setting.py

@@ -1,5 +1,42 @@
-"""
-setting -
-auther: tanlie
-date: 2026/8/23
-"""
+"""Application configuration settings."""
+
+import os
+from dotenv import load_dotenv
+
+# Load .env from project root (if present)
+load_dotenv()
+
+
+class BaseConfig:
+    """Base configuration shared by all environments."""
+
+    SECRET_KEY = os.getenv("SECRET_KEY", "dev-secret-key")
+    DEBUG = False
+    TESTING = False
+
+
+class DevelopmentConfig(BaseConfig):
+    """Development configurations."""
+
+    DEBUG = True
+
+
+class ProductionConfig(BaseConfig):
+    """Production configurations."""
+
+    DEBUG = False
+
+
+class TestingConfig(BaseConfig):
+    """Testing configurations."""
+
+    TESTING = True
+    DEBUG = True
+
+
+config = {
+    "development": DevelopmentConfig,
+    "production": ProductionConfig,
+    "testing": TestingConfig,
+    "default": DevelopmentConfig,
+}

+ 9 - 0
app/routes/health.py

@@ -0,0 +1,9 @@
+from flask import Blueprint, jsonify
+
+bp = Blueprint("health", __name__)
+
+
+@bp.route("/health", methods=["GET"])
+def health():
+    """Simple health check endpoint."""
+    return jsonify({"status": "ok"})

+ 30 - 0
app/utils/logger.py

@@ -0,0 +1,30 @@
+import logging
+from logging.config import dictConfig
+
+
+def setup_logging(app):
+    """Configure basic logging for the application."""
+    level = logging.DEBUG if app.config.get("DEBUG") else logging.INFO
+
+    config = {
+        "version": 1,
+        "disable_existing_loggers": False,
+        "formatters": {
+            "default": {
+                "format": "%(asctime)s %(levelname)s %(name)s: %(message)s",
+            }
+        },
+        "handlers": {
+            "console": {
+                "class": "logging.StreamHandler",
+                "formatter": "default",
+                "level": level,
+            }
+        },
+        "root": {
+            "handlers": ["console"],
+            "level": level,
+        },
+    }
+
+    dictConfig(config)

+ 5 - 9
ginger.py

@@ -1,12 +1,8 @@
-"""
-ginger -
-auther: tanlie
-date: 2026/8/23
-"""
-from app.app import create_app
+"""Application entrypoint."""
 
-app = create_app()
+from app.app import create_app
 
+app = create_app("development")
 
-if __name__ == '__main__':
-    app.run(debug=True)
+if __name__ == "__main__":
+    app.run(host="0.0.0.0", port=5000, debug=True)

+ 2 - 0
requirements.txt

@@ -1 +1,3 @@
 Flask==3.1.3
+python-dotenv
+pytest

+ 16 - 0
tests/test_health.py

@@ -0,0 +1,16 @@
+import pytest
+
+from app.app import create_app
+
+
+@pytest.fixture()
+def app():
+    app = create_app("testing")
+    return app
+
+
+def test_health(app):
+    client = app.test_client()
+    resp = client.get("/health")
+    assert resp.status_code == 200
+    assert resp.get_json() == {"status": "ok"}