YouTip LogoYouTip

Flask Blog Deploy

In this chapter, you will learn the application factory pattern, production environment configuration, and how to deploy the Flask blog to Railway. * * * ## Application Factory Pattern create_app() So far, `app = Flask(__name__)` has been directly created in app.py, which works for development, but there are several problems: * Unable to create independent app instances during testing * Unable to switch different configurations by environment (development/testing/production) * Extension initialization is tightly coupled with the app instance The application factory pattern solves these problems: encapsulate the creation of app into a function. ## Example # File path: app/__init__.py from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_login import LoginManager from flask_migrate import Migrate from config import Config db = SQLAlchemy() login_manager = LoginManager() migrate = Migrate() def create_app(config_class=Config): """Application Factory: Create Flask application instance based on configuration class""" app = Flask( __name__ ) app.config.from_object(config_class) # Initialize extensions (first create app instance, then bind extensions to app) db.init_app(app) login_manager.init_app(app) migrate.init_app(app, db) login_manager.login_view='auth.login' login_manager.login_message='Please log in first before accessing.' # Register Blueprint from app.blueprints.main import main_bp from app.blueprints.posts import posts_bp from app.blueprints.auth import auth_bp from app.blueprints.user import user_bp app.register_blueprint(main_bp) app.register_blueprint(posts_bp) app.register_blueprint(auth_bp) app.register_blueprint(user_bp) # user_loader needs to be defined after app exists from app.models import User @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) return app ### Configuration file config.py ## Example # File path: config.py import os from dotenv import load_dotenv # Load environment variables from .env file (only used in development environment) load_dotenv() class Config: SECRET_KEY =os.environ.get('SECRET_KEY','dev-secret-key') SQLALCHEMY_DATABASE_URI =os.environ.get('DATABASE_URL','sqlite:///blog.db') SQLALCHEMY_TRACK_MODIFICATIONS =False class DevelopmentConfig(Config): DEBUG =True class ProductionConfig(Config): DEBUG =False # Select configuration based on environment variable config_map ={ 'development': DevelopmentConfig, 'production': ProductionConfig, 'default': DevelopmentConfig } ### New entry file wsgi.py ## Example # File path: wsgi.py from app import create_app app = create_app() Now the startup method becomes: (venv) $ flask --app wsgi run --debug # Development mode(venv) $ gunicorn wsgi:app # Production mode (Gunicorn) > Note the import order: Blueprint and user_loader must be imported inside create_app() (not at the top of the file), otherwise it will trigger circular imports (Blueprint references models, models references db, and db is not yet bound to app). * * * ## Generate requirements.txt and Procfile (venv) $ pip freeze > requirements.txt Make sure the file contains key dependencies: Flask, Flask-SQLAlchemy, Flask-Migrate, Flask-Login, Flask-WTF, Flask-Admin, gunicorn, python-dotenv. Create `Procfile` in the project root directory: web: gunicorn wsgi:app * * * ## Push the project to GitHub $ git init $ echo "venv/" > .gitignore $ echo "__pycache__/" >> .gitignore $ echo "*.pyc" >> .gitignore $ echo "instance/" >> .gitignore $ echo ".env" >> .gitignore $ git add . $ git commit -m "Initialize Flask blog project" $ git branch -M main $ git remote add origin https://github.com/your username/flask-blog.git $ git push -u origin main > Be sure to add `.env` to `.gitignore`. The .env file contains sensitive information such as SECRET_KEY. Once committed to GitHub, it cannot be completely deleted (Git history will retain it). * * * ## Railway Deployment 1. Visit [railway.app](https://railway.app/), log in with GitHub 2. New Project β†’ Deploy from GitHub repo β†’ Select flask-blog 3. Railway automatically detects Procfile and identifies the Gunicorn startup command 4. Set environment variables in Variables 5. Click Deploy ### Environment Variable Configuration | Variable Name | Value | Description | | --- | --- | --- | | SECRET_KEY | Randomly generated long string | Encrypt Session and CSRF Token | | DATABASE_URL | Automatically injected by Railway | Production database (Railway provides PostgreSQL) | | FLASK_ENV | production | Production environment identifier | Quickly generate SECRET_KEY: $ python -c "import secrets; print(secrets.token_urlsafe(50))" After successful deployment, you get a link like `https://flask-blog.up.railway.app`. * * * ## Next Learning Direction | Learning Direction | Suitable For | Recommended Starting Point | | --- | --- | --- | | Flask REST API | Building API for frontend frameworks (Vue3/React) | Use jsonify instead of render_template to build RESTful interfaces | | Flask + Vue3/React Frontend-Backend Separation | Want to use Flask as backend and Vue3/React as frontend | Flask provides JSON API, frontend communicates via fetch | | PostgreSQL | Need production-grade database | Replace SQLite, install psycopg2, modify DATABASE_URL | | Docker Deployment | Containerized deployment | Write Dockerfile, orchestrate with docker-compose |
← Fastapi Blog Jinja2 TemplatesFlask Blog Wtf β†’