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 |
YouTip