Hello and welcome, aspiring web developers! Today, we’re going to embark on an exciting journey: building a simple blog from scratch using Flask. If you’ve ever wanted to create your own corner on the internet where you can share your thoughts, this is a fantastic place to start. Flask is a wonderful tool for this because it’s lightweight and easy to understand, making it perfect for beginners.
What is Flask?
Flask is what we call a “micro web framework” for Python.
* Web Framework: Think of a web framework as a toolkit that provides a structure and common tools to build web applications faster and more efficiently. Instead of writing every single line of code for common tasks like handling web requests, managing databases, or displaying web pages, a framework gives you a head start.
* Micro: This means Flask comes with just the essentials. It doesn’t force you into specific ways of doing things, giving you a lot of flexibility. This makes it easier to learn and understand each component individually.
With Flask, you can build all sorts of web applications, from small personal sites to more complex services. For our blog, we’ll focus on displaying articles and allowing you to add new ones.
Setting Up Your Workspace
Before we write any code, we need to set up our environment. Think of this as preparing your workshop with all the necessary tools.
1. Python Installation
First, make sure you have Python installed on your computer. Flask is a Python framework, so Python is essential! You can download it from the official Python website: python.org. We recommend Python 3.7 or newer.
2. Create a Virtual Environment
A virtual environment is a self-contained directory that holds a specific version of Python and any libraries (packages) you install for a particular project. It’s like having separate toolboxes for different projects, preventing conflicts between different versions of libraries.
Open your terminal or command prompt and navigate to where you want to create your project folder. Then, follow these steps:
- Create a new project folder:
bash
mkdir my_simple_blog
cd my_simple_blog -
Create the virtual environment:
bash
python3 -m venv venv
(On some systems, you might just usepython -m venv venv.)
This command creates a folder namedvenvinsidemy_simple_blog, which contains your isolated Python environment. -
Activate the virtual environment:
- On macOS/Linux:
bash
source venv/bin/activate - On Windows (Command Prompt):
bash
venv\Scripts\activate.bat - On Windows (PowerShell):
bash
venv\Scripts\Activate.ps1
You’ll know it’s active when you see(venv)at the beginning of your terminal prompt.
- On macOS/Linux:
3. Install Flask and Flask-SQLAlchemy
Now that our virtual environment is active, we can install Flask and another library called Flask-SQLAlchemy.
* pip: This is Python’s package installer. We use it to download and install libraries like Flask.
* Flask-SQLAlchemy: This is an extension that makes it easier to work with databases in Flask applications. We’ll use it to store our blog posts.
pip install Flask Flask-SQLAlchemy
Your First Flask App: “Hello, Blog!”
Let’s create our very first Flask application. In your my_simple_blog folder, create a new file named app.py.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_blog():
return "Hello, Bloggers! Welcome to my simple Flask blog."
if __name__ == '__main__':
app.run(debug=True)
Let’s break down this small program:
* from flask import Flask: This line imports the Flask class, which is the heart of our application.
* app = Flask(__name__): This creates an instance of our Flask application. __name__ is a special Python variable that tells Flask where to find resources like templates.
* @app.route('/'): This is a “decorator.” It tells Flask that whenever someone visits the root URL (e.g., http://127.0.0.1:5000/), the function immediately below it (hello_blog) should be executed.
* def hello_blog():: This is a Python function that returns a simple string. Flask takes this string and sends it back to the user’s web browser.
* if __name__ == '__main__': app.run(debug=True): This code ensures that our Flask application starts running only if this script is executed directly (not imported as a module). debug=True is very helpful during development as it automatically reloads the server when you make changes and provides detailed error messages. Remember to turn debug=False for production!
To run this app, save app.py, go back to your terminal (with the virtual environment active!), and type:
flask run
You should see output similar to this:
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 123-456-789
Open your web browser and go to http://127.0.0.1:5000/. You should see “Hello, Bloggers! Welcome to my simple Flask blog.” Congratulations, you’ve built your first Flask app! Press CTRL+C in your terminal to stop the server.
Introducing a Database: SQLite & Flask-SQLAlchemy
A blog needs to store posts! We’ll use SQLite, which is a simple file-based database (perfect for small projects and development), and Flask-SQLAlchemy to interact with it.
Database Configuration in app.py
Let’s modify app.py to configure our database. Add these lines after app = Flask(__name__) and before @app.route('/').
from flask_sqlalchemy import SQLAlchemy
import datetime
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
Defining Blog Posts (Models)
Now we need to tell our database what a “blog post” looks like. We do this by creating a “model.”
* Model: In Flask-SQLAlchemy, a model is a Python class that represents a table in your database. Each instance of the class will correspond to a row in that table.
Let’s define a Post model in app.py after db = SQLAlchemy(app):
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
# 'id' is a unique number for each post, automatically generated (primary key).
title = db.Column(db.String(100), nullable=False)
# 'title' is a string up to 100 characters, cannot be empty (nullable=False).
content = db.Column(db.Text, nullable=False)
# 'content' is for the main body of the post, can be long text.
created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow)
# 'created_at' stores the date and time the post was created,
# defaults to the current UTC time.
def __repr__(self):
# This method defines how a Post object is represented when printed, useful for debugging.
return f'<Post {self.title}>'
Creating the Database
With our model defined, we need to create the actual database file (blog.db) and the post table inside it.
Open your Python interactive shell in the terminal (make sure your virtual environment is active!):
python
Then, inside the Python shell:
from app import app, db
app.app_context().push() # Essential for Flask-SQLAlchemy to know which app context to use
db.create_all() # This creates all the tables defined in our models
exit()
You should now see a blog.db file in your my_simple_blog directory!
Creating Basic Web Pages (Routes & Templates)
We need a way to display our blog posts and a form to add new ones. This involves routes (what URL does what) and templates (how the web pages look).
1. Preparing Templates
Flask uses a templating engine called Jinja2. This allows us to write HTML files with special placeholders that Flask can fill with dynamic data (like our blog posts).
Create a new folder named templates inside your my_simple_blog directory. Inside templates, create two files: index.html and create.html.
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Simple Flask Blog</title>
<style>
body { font-family: sans-serif; margin: 2em; background-color: #f4f4f4; color: #333; }
h1, h2 { color: #0056b3; }
.post { background-color: #fff; padding: 1em; margin-bottom: 1em; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.post h3 { margin-top: 0; color: #333; }
.post small { color: #777; font-size: 0.8em; }
.add-link { display: inline-block; background-color: #28a745; color: white; padding: 0.8em 1.2em; border-radius: 5px; text-decoration: none; margin-bottom: 1em; }
.add-link:hover { background-color: #218838; }
</style>
</head>
<body>
<h1>Welcome to My Simple Flask Blog!</h1>
<a href="/create" class="add-link">Create New Post</a>
{% for post in posts %}
<div class="post">
<h3>{{ post.title }}</h3>
<small>Published on: {{ post.created_at.strftime('%Y-%m-%d %H:%M') }}</small>
<p>{{ post.content }}</p>
</div>
{% else %}
<p>No posts yet. Why not create one?</p>
{% endfor %}
</body>
</html>
{% for post in posts %}: This is a Jinja2 loop. It iterates over a list ofpoststhat Flask will provide.{{ post.title }}: These are placeholders. Flask will replace{{ post.title }}with the actual title of each post.{% else %}: This is a Jinja2 feature that displays content if the loop doesn’t run (i.e.,postsis empty).
templates/create.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Create a New Post</title>
<style>
body { font-family: sans-serif; margin: 2em; background-color: #f4f4f4; color: #333; }
h1 { color: #0056b3; }
form { background-color: #fff; padding: 2em; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); max-width: 600px; margin-top: 1em; }
label { display: block; margin-bottom: 0.5em; font-weight: bold; }
input[type="text"], textarea { width: 100%; padding: 0.8em; margin-bottom: 1em; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }
textarea { min-height: 150px; resize: vertical; }
button { background-color: #007bff; color: white; padding: 0.8em 1.5em; border: none; border-radius: 5px; cursor: pointer; font-size: 1em; }
button:hover { background-color: #0056b3; }
.back-link { display: inline-block; margin-top: 1em; color: #007bff; text-decoration: none; }
.back-link:hover { text-decoration: underline; }
</style>
</head>
<body>
<h1>Create a New Blog Post</h1>
<form method="POST">
<label for="title">Title:</label>
<input type="text" id="title" name="title" required>
<label for="content">Content:</label>
<textarea id="content" name="content" required></textarea>
<button type="submit">Publish Post</button>
</form>
<a href="/" class="back-link">Back to Posts</a>
</body>
</html>
<form method="POST">: This HTML form will send data to our Flask app when submitted.method="POST"is used for sending data that changes the server state (like creating a new post).name="title"andname="content": These are important! Flask will use these names to retrieve the data from the form.
2. Updating app.py with Routes
Now, let’s update app.py to use these templates and interact with our database. We’ll modify the hello_blog route and add a new create route.
First, add render_template, request, and redirect, url_for to your imports:
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
import datetime
Now, replace the hello_blog function and add the new create_post function:
@app.route('/')
def index():
# Query all posts from the database, ordered by creation date (newest first)
posts = Post.query.order_by(Post.created_at.desc()).all()
# Render the index.html template and pass the 'posts' list to it
return render_template('index.html', posts=posts)
@app.route('/create', methods=['GET', 'POST'])
def create_post():
# This route handles both GET requests (to display the form)
# and POST requests (when the form is submitted).
if request.method == 'POST':
# If it's a POST request, get data from the form
title = request.form['title']
content = request.form['content']
# Create a new Post object
new_post = Post(title=title, content=content)
try:
# Add the new post to the database session
db.session.add(new_post)
# Commit the changes to the database
db.session.commit()
# Redirect the user back to the homepage after successful creation
return redirect(url_for('index'))
except:
# Basic error handling
return "There was an issue adding your post."
else:
# If it's a GET request, just render the create.html form
return render_template('create.html')
Explanation of the new parts:
* render_template('index.html', posts=posts): This function tells Flask to find index.html in the templates folder, process it with Jinja2, and pass the posts variable to it.
* @app.route('/create', methods=['GET', 'POST']): This route can handle two types of HTTP requests:
* GET: When you just visit /create in your browser to see the form.
* POST: When you submit the form on the /create page.
* request.method == 'POST': This checks if the current request is a form submission.
* request.form['title']: This gets the value from the input field named title in the submitted form.
* db.session.add(new_post): This stages our new Post object to be added to the database.
* db.session.commit(): This saves the changes permanently to the blog.db file.
* redirect(url_for('index')): This tells the user’s browser to go to a different URL (in this case, the homepage, which is handled by the index function). url_for() is a smart way to generate URLs based on function names.
Running Your Blog
Now that everything is set up, let’s run your blog!
- Save all your changes: Make sure
app.py,templates/index.html, andtemplates/create.htmlare saved. - Ensure your virtual environment is active.
- Run the Flask application:
bash
flask run - Open your web browser and go to
http://127.0.0.1:5000/.
You should see your blog’s homepage. It will likely say “No posts yet.” Click on “Create New Post,” fill in a title and content, and hit “Publish Post.” You’ll be redirected back to the homepage, and your new post should appear!
Next Steps & Beyond
Congratulations! You’ve successfully built a simple blog using Flask, complete with a database and dynamic web pages. This is a solid foundation. Here are some ideas for what you can do next:
- Edit and Delete Posts: Add routes and forms to modify existing posts or remove them.
- User Authentication: Allow users to register, log in, and only let logged-in users create or edit posts.
- Styling (CSS): Make your blog look even better by adding more custom CSS.
- Comments: Implement a feature for readers to leave comments on posts.
- Deployment: Learn how to deploy your Flask app to a real server so others can see it!
Building web applications is a journey of continuous learning. Flask is a fantastic starting point because it lets you understand the core concepts without too much abstraction. Keep experimenting, keep building, and happy coding!
Leave a Reply
You must be logged in to post a comment.