π§± Part 1: Introduction to Flask
π― Goal:
By the end of this part, you’ll have a working Flask setup and a basic folder structure ready for your blog project.
π‘ What is Flask?
Flask is a lightweight web framework written in Python. It lets you build websites and web applications quickly and easily.
Think of Flask as the brain of your blog β it decides what happens when someone visits a page, fills out a form, or clicks a button.
π§ You already know Python β now youβll use it to build a real web app!
π§° Step 1: Set Up Your Environment
β What you need:
- Python 3.8+
- A code editor (like VS Code)
- A terminal (Command Prompt, Terminal, or VS Code terminal)
π¦ Step 2: Install Flask
π Create a Project Folder
- Open your terminal.
- Navigate to where you want to make the project.
- Create and move into a folder:
mkdir flask_blog
cd flask_blog
π§ͺ (Optional) Create a Virtual Environment
This keeps your projectβs packages separate from other projects.
python -m venv venv
Activate it:
- Windows:
venv\Scripts\activate
- macOS/Linux:
source venv/bin/activate
π’ Youβll know itβs activated when you see
(venv)
at the start of your terminal line.
π₯ Install Flask
pip install Flask
πΎ Save your dependencies:
pip freeze > requirements.txt
This creates a file with all the packages your app needs.
ποΈ Step 3: Set Up Your Project Structure
Inside your flask_blog
folder, create these:
flask_blog/
βββ static/ β CSS, images, etc.
βββ templates/ β HTML files go here
βββ app.py β Your main Flask app
βββ requirements.txt β List of packages used
βοΈ Step 4: Create Your First Flask App
In app.py
, write this:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "Hello, Flask!"
if __name__ == "__main__":
app.run(debug=True)
π Step 5: Run Your Flask App
In the terminal:
python app.py
Youβll see something like:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Open a browser and go to http://127.0.0.1:5000
. You should see:
Hello, Flask!
π§Ή Bonus: Use Flaskβs Development Mode
To make coding easier, turn on debug mode (already included with debug=True
). This auto-refreshes the app when you save changes.
π§ Recap
- You learned what Flask is.
- You installed Flask and set up your project.
- You created your first Flask app and saw it in the browser!
π Coming Up in Part 2…
Youβll set up a database, create your first Post model, and display posts on the homepage.
π§± Part 2: Setting Up the Flask Project and Database
π― Goal:
Set up a database to store blog posts. Youβll also create a Post
model with the following fields:
- Title
- Author
- Date
- Content
By the end of this part, your app will be ready to create and store blog post data!
π§° Step 1: Install Flask-SQLAlchemy
Flask doesnβt include a database by default, but we can easily add one using Flask-SQLAlchemy, a powerful and beginner-friendly extension.
In your terminal:
pip install Flask-SQLAlchemy
Then update your requirements.txt
:
pip freeze > requirements.txt
π§ SQLAlchemy is a library that helps us talk to a database using Python instead of writing SQL code directly.
ποΈ Step 2: Configure the Database in app.py
Open app.py
and update it to include SQLAlchemy:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
# π§ Database configuration
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
db = SQLAlchemy(app)
π§
sqlite:///blog.db
means: “create a SQLite database file called blog.db in this folder.”
π§± Step 3: Create the Post Model
Still in app.py
, below your db = SQLAlchemy(app)
line, add this class:
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
date_posted = db.Column(db.DateTime, default=datetime.utcnow)
author = db.Column(db.String(50), nullable=False)
content = db.Column(db.Text, nullable=False)
def __repr__(self):
return f"Post('{self.title}', '{self.date_posted}')"
Letβs break this down:
id
: A unique number for each posttitle
: Max 100 characters, cannot be blankdate_posted
: Automatically set to the current date/timeauthor
: Who wrote the postcontent
: The main text of the post
π¦ Step 4: Create the Database
In your terminal, open Python:
python
Then type the following inside the Python shell:
from app import app, db
with app.app_context():
db.create_all()
exit()
This creates a blog.db
file in your folder.
β Step 5: Check That It Works
Letβs quickly test it by creating a fake blog post (optional):
python
Then:
from app import app, db, Post
post = Post(title="My First Post", author="Jamie", content="This is my first blog post!")
with app.app_context():
db.session.add(post)
db.session.commit()
exit()
You just added your first blog post directly into the database! π
π§ Recap
- You installed Flask-SQLAlchemy
- You set up your database configuration
- You created a Post model
- You created your first real database entry
π Coming Up in Part 3…
Weβll build a homepage to show your blog posts and learn how to create and use HTML templates with Flask.
π§± Part 3: Creating Routes and Templates
π― Goal:
- Display blog posts on a homepage using an HTML template.
- Learn how Flask connects Python to HTML.
- Use Jinja2, Flaskβs built-in template engine, to loop through posts and show them on the page.
ποΈ Step 1: Create the templates
Folder
Flask automatically looks for HTML files in a folder called templates
.
In your project directory, make sure you have this structure:
flask_blog/
βββ static/
βββ templates/
β βββ home.html
βββ app.py
βββ blog.db
Create a new file: templates/home.html
π¬ Step 2: Create the Homepage Route
Open app.py
and update it to include:
from flask import render_template
@app.route("/")
def home():
posts = Post.query.order_by(Post.date_posted.desc()).all()
return render_template("home.html", posts=posts)
What does this do?
@app.route("/")
: This function runs when someone goes to the homepage (/
)Post.query.order_by(...)
: Gets all posts from the database, newest firstrender_template(...)
: Loads an HTML file and gives it theposts
to display
π§Ύ Step 3: Create the Template
In templates/home.html
, add this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Blog</title>
</head>
<body>
<h1>My Blog</h1>
{% for post in posts %}
<div style="border:1px solid #ccc; padding:10px; margin:10px 0;">
<h2>{{ post.title }}</h2>
<small>By {{ post.author }} on {{ post.date_posted.strftime('%B %d, %Y') }}</small>
<p>{{ post.content }}</p>
</div>
{% else %}
<p>No posts yet!</p>
{% endfor %}
</body>
</html>
π Letβs break this down:
{% for post in posts %}
: Loops through the list of blog posts{{ post.title }}
: Inserts the title from the database{% else %}
: Shows βNo posts yet!β if the list is empty
π§ This template uses Jinja2, a special syntax inside HTML for Python-like logic.
π§ͺ Step 4: Test It Out
- Run your Flask app:
python app.py
- Go to http://127.0.0.1:5000
- You should see your sample post(s) from Part 2!
π¨ (Optional) Step 5: Add Some Style
You can add a style.css
file inside the static
folder later.
Weβll focus on that in another part of the tutorial β but feel free to play with font sizes, colors, or layout!
π§ Recap
- You learned how to connect a route (
/
) to a template (home.html
) - You passed data (blog posts) from Python to HTML
- You used Jinja2 to loop through and display posts on the page
π Coming Up in Part 4β¦
We’ll add the ability to create new blog posts using a form, and save them into the database!
π§± Part 4: Creating New Posts with a Form
π― Goal:
- Add a form page where users can create a new blog post.
- Save the new post into the database.
- Redirect users back to the homepage to see their post.
π§° Step 1: Add a Route for New Posts
Open app.py
and add this below the home()
route:
from flask import request, redirect, url_for
@app.route("/new", methods=["GET", "POST"])
def new_post():
if request.method == "POST":
post_title = request.form["title"]
post_author = request.form["author"]
post_content = request.form["content"]
new_post = Post(title=post_title, author=post_author, content=post_content)
db.session.add(new_post)
db.session.commit()
return redirect(url_for("home"))
return render_template("new_post.html")
Letβs break it down:
methods=["GET", "POST"]
: Allows the page to both show the form (GET) and handle the form submission (POST).request.form[...]
: Gets the values the user typed.db.session.add(...)
: Adds the post to the database.redirect(url_for("home"))
: Sends the user back to the homepage.
π Step 2: Create new_post.html
In the templates
folder, make a new file called new_post.html
.
Add this code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>New Post</title>
</head>
<body>
<h1>Create a New Blog Post</h1>
<form method="POST">
<label>Title:</label><br>
<input type="text" name="title" required><br><br>
<label>Author:</label><br>
<input type="text" name="author" required><br><br>
<label>Content:</label><br>
<textarea name="content" rows="6" cols="40" required></textarea><br><br>
<button type="submit">Post</button>
</form>
<p><a href="/">Back to home</a></p>
</body>
</html>
π§ͺ Step 3: Test It Out!
- Run your app if itβs not running:
python app.py
- Visit http://127.0.0.1:5000/new
- Fill in a post and submit it.
- You should be redirected to the homepage, and your new post will be there!
β Bonus: Link to the New Post Page
Add this link at the top of your home.html
page just under <h1>My Blog</h1>
, so users can easily add posts:
<p><a href="/new">Create New Post</a></p>
π§ Recap
- You created a new route (
/new
) for writing posts - You built an HTML form
- You handled form data and saved it to the database
- You redirected users after submitting
π Coming Up in Part 5β¦
Weβll learn how to edit and delete posts so students can fully manage their blog entries.
π§± Part 5: Editing and Deleting Posts
π― Goal:
- Add Edit and Delete buttons to each blog post.
- Create pages for editing posts.
- Handle deleting posts from the database.
βοΈ Step 1: Add Edit and Delete Links to home.html
Open templates/home.html
and update each post block to include Edit and Delete links.
Replace this part:
<h2>{{ post.title }}</h2>
<small>By {{ post.author }} on {{ post.date_posted.strftime('%B %d, %Y') }}</small>
<p>{{ post.content }}</p>
With this:
<h2>{{ post.title }}</h2>
<small>By {{ post.author }} on {{ post.date_posted.strftime('%B %d, %Y') }}</small>
<p>{{ post.content }}</p>
<a href="/edit/{{ post.id }}">Edit</a> |
<a href="/delete/{{ post.id }}" onclick="return confirm('Are you sure you want to delete this post?');">Delete</a>
π§
post.id
is the unique ID of each blog post, which lets us target specific ones.
π§° Step 2: Add the Edit Route
Open app.py
and add this below your other routes:
@app.route("/edit/<int:id>", methods=["GET", "POST"])
def edit_post(id):
post = Post.query.get_or_404(id)
if request.method == "POST":
post.title = request.form["title"]
post.author = request.form["author"]
post.content = request.form["content"]
db.session.commit()
return redirect(url_for("home"))
return render_template("edit_post.html", post=post)
π Step 3: Create edit_post.html
In your templates/
folder, create a file called edit_post.html
and add this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Edit Post</title>
</head>
<body>
<h1>Edit Post</h1>
<form method="POST">
<label>Title:</label><br>
<input type="text" name="title" value="{{ post.title }}" required><br><br>
<label>Author:</label><br>
<input type="text" name="author" value="{{ post.author }}" required><br><br>
<label>Content:</label><br>
<textarea name="content" rows="6" cols="40" required>{{ post.content }}</textarea><br><br>
<button type="submit">Update</button>
</form>
<p><a href="/">Back to home</a></p>
</body>
</html>
π§Ή Step 4: Add the Delete Route
Back in app.py
, add this below the edit route:
@app.route("/delete/<int:id>")
def delete_post(id):
post = Post.query.get_or_404(id)
db.session.delete(post)
db.session.commit()
return redirect(url_for("home"))
β οΈ This route deletes a post immediately after the user confirms from the browser popup.
π§ͺ Step 5: Test Everything
- Visit the homepage.
- Click Edit on a post β change some text and save.
- Click Delete on a post β confirm the popup and check that it disappears.
- Try deleting a post that doesnβt exist by typing
/delete/999
β Flask should show a 404 page.
π§ Recap
- You added Edit and Delete buttons
- You created a form to update posts
- You built a route to delete posts safely
- Your blog app now supports full CRUD (Create, Read, Update, Delete)!
π¨ Part 6: Adding Some Basic CSS Styling
π― Goal:
- Make the blog look cleaner and more readable.
- Add consistent fonts, spacing, and colors.
- Keep everything simple with custom CSS.
π§° Step 1: Create a Static Folder for CSS
Flask expects static files like CSS or images to go in a folder called static
.
π Inside your project directory, create a new folder named static
, and inside that, create a file called style.css
.
/project-folder
β
βββ static/
β βββ style.css
π¨ Step 2: Write Some Simple CSS
Open static/style.css
and add the following:
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
color: #333;
padding: 20px;
max-width: 800px;
margin: auto;
}
h1, h2 {
color: #444;
}
a {
color: #0066cc;
text-decoration: none;
margin-right: 10px;
}
a:hover {
text-decoration: underline;
}
form {
background-color: #fff;
padding: 15px;
border-radius: 8px;
box-shadow: 0 0 5px rgba(0,0,0,0.1);
}
input[type="text"], textarea {
width: 100%;
padding: 8px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
background-color: #007BFF;
color: white;
padding: 10px 15px;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
.post {
background-color: #fff;
padding: 15px;
margin-bottom: 20px;
border-radius: 6px;
box-shadow: 0 0 4px rgba(0,0,0,0.1);
}
π§© Step 3: Link the CSS to Your HTML Templates
Open each of your templates (home.html
, new_post.html
, edit_post.html
) and add this <link>
in the <head>
section:
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
For example, your updated home.html
head would look like:
<head>
<meta charset="UTF-8">
<title>My Blog</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
β
Repeat for the other pages too (new_post.html
, edit_post.html
).
β¨ Step 4: Add a Class to Blog Post Blocks
Now letβs use our .post
CSS class. In home.html
, wrap each blog post like this:
<div class="post">
<h2>{{ post.title }}</h2>
<small>By {{ post.author }} on {{ post.date_posted.strftime('%B %d, %Y') }}</small>
<p>{{ post.content }}</p>
<a href="/edit/{{ post.id }}">Edit</a>
<a href="/delete/{{ post.id }}" onclick="return confirm('Are you sure?');">Delete</a>
</div>
π§ͺ Step 5: Refresh and Check
- Restart your Flask server (if needed).
- Visit your blog pages in the browser.
- Everything should now look cleaner, with nice spacing, fonts, buttons, and post containers.
π§ Recap
- You learned how to use Flaskβs
static
folder. - You wrote and linked a simple CSS file.
- You gave your blog a fresh and more professional look!
β Part 7: Review and Whatβs Next
π― Goal:
- Review what students learned.
- Provide a checklist to ensure everything works.
- Suggest extension ideas for further exploration.
π Review Checklist
Letβs make sure your blog is fully functional. Students should go through this checklist:
π¨ Functionality
Feature | Check |
---|---|
Homepage displays all blog posts | β |
Each post shows title, author, date, and content | β |
You can create a new post using a form | β |
You can edit a post and save changes | β |
You can delete a post with a confirmation | β |
πΌοΈ Styling
Feature | Check |
---|---|
CSS is applied to all pages | β |
Posts are inside styled containers | β |
Buttons and links are styled and easy to read | β |
Font and layout are consistent across pages | β |
π Code Structure
Feature | Check |
---|---|
app.py contains route logic and database setup | β |
You are using templates for each page (home.html , new_post.html , edit_post.html ) | β |
Static files (like style.css ) are stored in the correct folder | β |
Code is indented and commented neatly | β |
π§ What You Learned
By building this blog, you learned:
β
How to use Flask, a Python web framework
β
How to work with HTML templates using Jinja2
β
How to create and structure a Flask project
β
How to use Flask-SQLAlchemy to manage a database
β
How to perform full CRUD operations (Create, Read, Update, Delete)
β
How to apply basic CSS styling to your web app
π Extension Ideas (Optional)
When students are ready to take the project further, here are some fun ideas:
π οΈ Functional Extensions
- β Add a search bar to filter posts by keyword.
- β Add categories or tags for each post.
- β Include commenting on posts (maybe using a nested list).
- β Show the number of words or reading time per post.
π©βπ¨ Design Extensions
- π¨ Add a responsive layout using Bootstrap.
- π¨ Add a navigation bar across pages.
- π¨ Include images with posts (using file upload or URLs).
π‘οΈ Advanced Extensions
- π Add user authentication (login/logout, passwords).
- π Show posts by date or sort them.
- π Deploy your blog to the web with Render, PythonAnywhere, or Replit.
π§³ Wrap-Up
Congratulations! Youβve just built a fully functional blog using Flask, from scratch. Whether youβre new to Python or web development, this project shows that youβre capable of building real web apps and solving problems creatively. π