Setup
Bash
pip install flask flask-sqlalchemy flask-login werkzeugmodels.py
Python
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
db = SQLAlchemy()
class User(UserMixin, db.Model):
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)
password_hash = db.Column(db.String(256))
posts = db.relationship("Post", backref="author", lazy=True)
def set_password(self, p): self.password_hash = generate_password_hash(p)
def check_password(self, p): return check_password_hash(self.password_hash, p)
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)app.py
Python
from flask import Flask, render_template, redirect, url_for, request, flash
from flask_login import LoginManager, login_user, logout_user, login_required, current_user
from models import db, User, Post
app = Flask(__name__)
app.config["SECRET_KEY"] = "change-in-production"
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///blog.db"
db.init_app(app)
login_manager = LoginManager(app)
login_manager.login_view = "login"
@login_manager.user_loader
def load_user(uid): return User.query.get(int(uid))
@app.route("/")
def index():
return render_template("index.html", posts=Post.query.order_by(Post.created_at.desc()).all())
@app.route("/new", methods=["GET", "POST"])
@login_required
def new_post():
if request.method == "POST":
post = Post(title=request.form["title"], content=request.form["content"], author=current_user)
db.session.add(post); db.session.commit()
return redirect(url_for("index"))
return render_template("new_post.html")
@app.route("/register", methods=["GET", "POST"])
def register():
if request.method == "POST":
user = User(username=request.form["username"], email=request.form["email"])
user.set_password(request.form["password"])
db.session.add(user); db.session.commit()
login_user(user); return redirect(url_for("index"))
return render_template("register.html")
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
user = User.query.filter_by(email=request.form["email"]).first()
if user and user.check_password(request.form["password"]):
login_user(user); return redirect(url_for("index"))
flash("Invalid credentials")
return render_template("login.html")
@app.route("/logout")
@login_required
def logout(): logout_user(); return redirect(url_for("index"))
with app.app_context(): db.create_all()
if __name__ == "__main__": app.run(debug=True)Bash
python app.py
# http://localhost:5000Tip: For production: Gunicorn as WSGI server, Nginx as reverse proxy. Never run Flask dev server in production.