🧱 Flask Project – Folder Structure
(From Scratch – Beginner Friendly)
🔹 STEP 1: Create a Main Project Folder
📌 Why?
To keep all Flask project files in one place.
▶ On Desktop (Windows)
1. Right-click on Desktop
2. Click New → Folder
3. Rename folder to:
flask_blog
🔹 STEP 2: Open Folder in VS Code
📌 Why?
VS Code will manage all files & terminal in one place.
1. Open VS Code
2. Click File → Open Folder
3. Select flask_blog
4. Click Select Folder
✔ Now this is your project root folder
🔹 STEP 3: Open Terminal Inside VS Code
📌 Why?
All commands should run inside project folder
1. Click Terminal → New Terminal
2. Check path:
Desktop\flask_blog>
✔ If you see this → you are in the correct folder
🔹 STEP 4: Create Virtual Environment Folder
📌 Why virtual environment?
● Keeps Flask libraries separate
● Avoids errors on other projects
▶ Command
python -m venv venv
✔ A new folder venv is created automatically
📂 Folder now:
flask_blog/
│ venv/
🔹 STEP 5: Activate Virtual Environment
📌 Very Important Step
▶ Windows
venv\Scripts\activate
✔ You will see:
(venv) Desktop\flask_blog>
🔹 STEP 6: Create Main Python File
📌 This file runs the Flask app
1. In VS Code Explorer → Right-click
2. Click New File
3. Name it:
[Link]
📂 Structure:
flask_blog/
│ venv/
│ [Link]
🔹 STEP 7: Create Templates Folder
📌 Why templates folder?
Flask requires HTML files to be inside templates
▶ Steps
1. Right-click in Explorer
2. Click New Folder
3. Name it:
templates
🔹 STEP 8: Create Static Folder
📌 Why static folder?
For CSS, JS, images
1. Right-click → New Folder
2. Name it:
static
📂 Structure:
flask_blog/
│ venv/
│ [Link]
│ templates/
│ static/
🔹 STEP 9: Create HTML Files (Inside templates)
📌 Each page = one HTML file
Create these files inside templates folder:
1. [Link] → common layout
2. [Link] → home page
3. add_post.html → add blog
4. edit_post.html → edit blog
5. [Link] → login page
6. [Link] → register page
📂 Now:
templates/
│ [Link]
│ [Link]
│ add_post.html
│ edit_post.html
│ [Link]
│ [Link]
🔹 STEP 10: Create CSS File
📌 For styling the website
Inside static folder:
1. Right-click → New File
2. Name it:
[Link]
🔹 STEP 11: Create Database Files
📌 These files handle database & settings
Create files in root folder:
1. [Link] → database tables
2. [Link] → app configuration
3. [Link] → installed packages
📂 Final Folder Structure:
flask_blog/
│ venv/
│ [Link]
│ [Link]
│ [Link]
│ [Link]
│
├── templates/
│ ├── [Link]
│ ├── [Link]
│ ├── add_post.html
│ ├── edit_post.html
│ ├── [Link]
│ └── [Link]
│
└── static/
└── [Link]
🔹 STEP 12: Install Flask Packages
📌 Only after venv activation
pip install flask flask-sqlalchemy flask-login flask-restful
🔹 STEP 13: Verify Everything (Important)
Ask students:
● ✔ venv created?
● ✔ (venv) visible?
● ✔ templates folder name correct?
● ✔ static folder name correct?
⚠️ Common Mistake
❌ template
✅ templates
📁 Flask Blog Project
✅ FILE 1: [Link]
🔹 EXPLANATION
● This file stores all libraries required for the project.
● Used when:
○ Project is shared
○ Project is deployed
● One command installs everything:
pip install -r [Link]
✅ [Link]
Flask
Flask-SQLAlchemy
Flask-Login
Flask-RESTful
Werkzeug
✅ [Link]
import os
BASE_DIR = [Link]([Link](__file__))
class Config:
SECRET_KEY = "secret123"
SQLALCHEMY_DATABASE_URI = "sqlite:///" + [Link](BASE_DIR,
"[Link]")
SQLALCHEMY_TRACK_MODIFICATIONS = False
✅ [Link]
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
db = SQLAlchemy()
class User(UserMixin, [Link]):
id = [Link]([Link], primary_key=True)
username = [Link]([Link](150), unique=True,
nullable=False)
password = [Link]([Link](200), nullable=False)
class Post([Link]):
id = [Link]([Link], primary_key=True)
title = [Link]([Link](200), nullable=False)
content = [Link]([Link], nullable=False)
✅ [Link]
from flask import Flask, render_template, request, redirect, url_for
from flask_login import LoginManager, login_user, login_required,
logout_user
from flask_restful import Api, Resource
from [Link] import generate_password_hash,
check_password_hash
from config import Config
from models import db, User, Post
app = Flask(__name__)
[Link].from_object(Config)
db.init_app(app)
api = Api(app)
# ---------- LOGIN ----------
login_manager = LoginManager(app)
login_manager.login_view = "login"
@login_manager.user_loader
def load_user(user_id):
return [Link](int(user_id))
# ---------- DB ----------
with app.app_context():
db.create_all()
# ---------- AUTH ----------
@[Link]("/register", methods=["GET", "POST"])
def register():
if [Link] == "POST":
hashed_password =
generate_password_hash([Link]["password"])
user = User(
username=[Link]["username"],
password=hashed_password
)
[Link](user)
[Link]()
return redirect(url_for("login"))
return render_template("[Link]")
@[Link]("/login", methods=["GET", "POST"])
def login():
if [Link] == "POST":
user = [Link].filter_by(
username=[Link]["username"]
).first()
if user and check_password_hash([Link],
[Link]["password"]):
login_user(user)
return redirect(url_for("index"))
return render_template("[Link]")
@[Link]("/logout")
@login_required
def logout():
logout_user()
return redirect(url_for("login"))
# ---------- BLOG ----------
@[Link]("/")
@login_required
def index():
posts = [Link]()
return render_template("[Link]", posts=posts)
@[Link]("/add", methods=["GET", "POST"])
@login_required
def add_post():
if [Link] == "POST":
post = Post(
title=[Link]["title"],
content=[Link]["content"]
)
[Link](post)
[Link]()
return redirect(url_for("index"))
return render_template("add_post.html")
@[Link]("/edit/<int:id>", methods=["GET", "POST"])
@login_required
def edit_post(id):
post = [Link].get_or_404(id)
if [Link] == "POST":
[Link] = [Link]["title"]
[Link] = [Link]["content"]
[Link]()
return redirect(url_for("index"))
return render_template("edit_post.html", post=post)
@[Link]("/delete/<int:id>")
@login_required
def delete_post(id):
post = [Link].get_or_404(id)
[Link](post)
[Link]()
return redirect(url_for("index"))
# ---------- API ----------
class PostAPI(Resource):
def get(self):
return [
{"id": [Link], "title": [Link], "content": [Link]}
for p in [Link]()
]
api.add_resource(PostAPI, "/api/posts")
# ---------- RUN ----------
if __name__ == "__main__":
[Link](debug=True)
✅ templates/[Link] (CHECKED)
<!DOCTYPE html>
<html>
<head>
<title>Flask Blog</title>
<link rel="stylesheet" href="{{ url_for('static',
filename='[Link]') }}">
</head>
<body>
<div class="container">
<h1>Flask Blog</h1>
<nav>
<a href="{{ url_for('index') }}">Home</a>
<a href="{{ url_for('add_post') }}">Add Post</a>
<a href="{{ url_for('logout') }}">Logout</a>
</nav>
<hr>
{% block content %}{% endblock %}
</div>
</body>
</html>
✅ templates/[Link]
{% extends "[Link]" %}
{% block content %}
{% for post in posts %}
<h2>{{ [Link] }}</h2>
<p>{{ [Link] }}</p>
<a href="/edit/{{ [Link] }}">Edit</a> |
<a href="/delete/{{ [Link] }}">Delete</a>
<hr>
{% endfor %}
{% endblock %}
✅ templates/add_post.html
{% extends "[Link]" %}
{% block content %}
<form method="POST">
<input type="text" name="title" placeholder="Title"
required><br><br>
<textarea name="content" placeholder="Content"
required></textarea><br><br>
<button>Add Post</button>
</form>
{% endblock %}
✅ templates/edit_post.html
{% extends "[Link]" %}
{% block content %}
<form method="POST">
<input type="text" name="title" value="{{ [Link] }}"
required><br><br>
<textarea name="content" required>{{ [Link]
}}</textarea><br><br>
<button>Update</button>
</form>
{% endblock %}
✅ templates/[Link]
<form method="POST">
<h2>Login</h2>
<input name="username" placeholder="Username" required><br><br>
<input name="password" type="password" placeholder="Password"
required><br><br>
<button>Login</button>
<p><a href="/register">Register</a></p>
</form>
✅ templates/[Link]
<form method="POST">
<h2>Register</h2>
<input name="username" placeholder="Username" required><br><br>
<input name="password" type="password" placeholder="Password"
required><br><br>
<button>Register</button>
</form>
✅ static/[Link] (CHECKED)
body {
font-family: Arial, sans-serif;
background: #f4f6f8;
}
.container {
width: 700px;
margin: auto;
background: white;
padding: 20px;
}
nav a {
margin-right: 10px;
text-decoration: none;
font-weight: bold;
}
input, textarea {
width: 100%;
padding: 8px;
}