Setup
pip install flask flask-sqlalchemy flask-login werkzeugmodels.py
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
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)python app.py
# http://localhost:5000🏋️ Practical Exercise
Extend the full-stack app:
- Add a new field to the model and update the template to display it.
- Add a form to create new records through the web interface.
- Add a route to delete a record.
- Add basic input validation on the form.
🔥 Challenge Exercise
Grow the app into a complete CRUD web application: add create, edit, and delete flows with forms, server-side validation, and flash messages for feedback. Add simple user authentication so only logged-in users can modify data, and separate concerns into models, routes, and templates. Bonus: deploy it and add a handful of tests for the key routes.
📋 Summary
- This project builds a full-stack web app with a database, server logic, and HTML templates.
- Models define the data, routes/views handle requests, and templates render the UI.
- Forms let users create and edit data, with validation on the server.
- Data persists in a database via an ORM or direct queries.
- Authentication restricts who can modify data.
- Clear separation of concerns keeps the app maintainable and testable.
Interview Questions on Building a Full-Stack App
- What does “full-stack” mean and what layers are involved?
- How does a web framework connect models, views, and templates?
- How do you handle form submissions and validation?
- How is data persisted in a web app?
- How do you add user authentication?
- What is the difference between server-side and client-side rendering?
- How would you deploy a Python web application?
Related Topics
FAQ
It spans the whole application: the front end (HTML/CSS/JS the user sees), the back end (server logic and routing), and the data layer (the database). A full-stack project ties all three together.
Models represent and persist data, views/routes handle incoming requests and decide what to do, and templates turn data into HTML for the browser. The framework wires a URL to a view, which queries models and renders a template.
Use the framework’s auth tools (Django’s built-in auth, or Flask extensions like Flask-Login). Store hashed passwords, create login/logout routes and a session, and protect sensitive routes so only authenticated users can reach them.
Run it behind a production server (Gunicorn/Uvicorn) with a reverse proxy like Nginx, on a platform such as a VPS, Railway, Render, or a container host. Use environment variables for secrets and a managed database in production.
