Dynamic Forms with Flask

A common need in web applications is to create a form that allows the user to enter a list of items, with the number of items not known in advance. This is a pattern often used when entering user information, specifically for phone numbers or addresses, but has a lot of other use … | Continue reading


@blog.miguelgrinberg.com | 8 days ago

Encryption at Rest with SQLAlchemy

In this tutorial I'm going to show you how to extend SQLAlchemy so that you can define database columns that are stored encrypted. In the solution I'm going to share, the columns that are designated as encrypted will transparently encrypt and decrypt themselves as data moves to a … | Continue reading


@blog.miguelgrinberg.com | 18 days ago

Using Free Let's Encrypt SSL Certificates in 2025

In this article I'm going to review the steps you need to take to obtain an A+ SSL security rating for your website, as mine has. This tutorial applies to any hosting solution that uses Nginx as web server or reverse proxy, running on a Debian based distribution of Linux such as … | Continue reading


@blog.miguelgrinberg.com | 24 days ago

A Year In Review: Flask in 2024

I'm seeing a stream of "year in review" blog posts about all sorts of topics pop up to coincide with the start of 2025. I'm not sure if this is going to be a new tradition for me, but to follow this trend in this article I'm going to give you my review of the most interesting thi … | Continue reading


@blog.miguelgrinberg.com | 1 month ago

Is Python Really That Slow?

My standard response when someone asks me how I deal with Python being such a slow language is that Python is by far the fastest to write, cleanest, more maintainable programming language I know, and that a bit of a runtime performance penalty is a small price to pay when I'm rew … | Continue reading


@blog.miguelgrinberg.com | 2 months ago

The Ultimate Guide to Error Handling in Python

I often come across developers who know the mechanics of Python error handling well, yet when I review their code I find it to be far from good. Exceptions in Python is one of those areas that have a surface layer that most people know, and a deeper, almost secret one that a lot … | Continue reading


@blog.miguelgrinberg.com | 4 months ago

How LLMs Work, Explained Without Math

I'm sure you agree that it has become impossible to ignore Generative AI (GenAI), as we are constantly bombarded with mainstream news about Large Language Models (LLMs). Very likely you have tried ChatGPT, maybe even keep it open all the time as an assistant. A basic question I t … | Continue reading


@blog.miguelgrinberg.com | 9 months ago

How To Add Dark Mode Support To Your Website

You may have noticed that I have recently added a dark mode to this blog. The default color theme now follows the theme setting in your operating system by default. Nice, right? I have implemented this feature entirely in the front end, using CSS and a touch of JavaScript. Intere … | Continue reading


@blog.miguelgrinberg.com | 1 year ago

How To Add Dark Mode Support To Your Website

You may have noticed that I have recently added a dark mode to this blog. The default color theme now follows the theme setting in your operating system by default, and you can also select which mode to enable from the top navigation bar. Nice, right? I have implemented this feat … | Continue reading


@blog.miguelgrinberg.com | 1 year ago

Eliza-GPT: The Classic ELIZA Chatbot Running On OpenAI's Chat Completions API

ELIZA is possibly the first chatbot ever created, dating back to 1966. It was created by Joseph Weizenbaum as an early experiment in natural language processing (NLP). ELIZA is able to hold a conversation in English with a human, and is programmed through a set of pattern matchin … | Continue reading


@blog.miguelgrinberg.com | 1 year ago

Eliza-GPT: The Classic ELIZA Chatbot Running On OpenAI's Chat Completions API

ELIZA is possibly the first chatbot ever created, dating back to 1966. It was created by Joseph Weizenbaum as an early experiment in natural language processing (NLP). ELIZA is able to hold a conversation in English with a human, and is programmed through a set of pattern matchin … | Continue reading


@blog.miguelgrinberg.com | 1 year ago

Microdot: Yet Another Python Web Framework

I just realized that I have never written on this blog about Microdot, my very own web framework for Python. I have released Microdot 2.0 a few days ago, so I guess this is a good time to make a belated announcement, and tell you why this world needs yet another Python web framew … | Continue reading


@blog.miguelgrinberg.com | 1 year ago

Microdot: Yet Another Python Web Framework

I just realized that I have never written on this blog about Microdot, my very own web framework for Python. I have released Microdot 2.0 a few days ago, so I guess this is a good time to make a belated announcement, and tell you why this world needs yet another Python web framew … | Continue reading


@blog.miguelgrinberg.com | 1 year ago

Announcing the Flask Mega-Tutorial, 2024 Edition

Today I'm super-excited to share that I have made available a major update to the Flask Mega-Tutorial, which I'm calling the "2024 Edition". In the following sections I'll re-introduce the tutorial in case you have not seen it before, and I'll also go over the changes and improve … | Continue reading


@blog.miguelgrinberg.com | 1 year ago

Announcing the Flask Mega-Tutorial, 2024 Edition

Today I'm super-excited to share that I have made available a major update to the Flask Mega-Tutorial, which I'm calling the "2024 Edition". In the following sections I'll re-introduce the tutorial in case you have not seen it before, and I'll also go over the changes and improve … | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XIX: Deployment on Docker Containers

This is the nineteenth installment of the Flask Mega-Tutorial series, in which I'm going to deploy Microblog to the Docker container platform.You are reading the 2024 edition of the Flask… | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XX: Some JavaScript Magic

This is the twentieth installment of the Flask Mega-Tutorial series, in which I'm going to add a nice popup when you hover your mouse over a user's nickname.You are reading the 2024 edition of the… | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XXI: User Notifications

This is the twenty first installment of the Flask Mega-Tutorial series, in which I'm going to add a private message feature, along with user notifications that appear in the navigation bar without the need to refresh the page. | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XXII: Background Jobs

This is the twenty second installment of the Flask Mega-Tutorial series, in which I'm going to tell you how to create background jobs that run independently of the web server.You are reading the 2024… | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XXIII: Application Programming Interfaces (APIs)

This is the twenty third and last installment of the Flask Mega-Tutorial series, in which I'm going to tell you how to extend microblog with an application programming interface (or API) that clients can use to work with the application in a more direct way than the traditional w … | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XXIII: Application Programming Interfaces (APIs)

This is the twenty third and last installment of the Flask Mega-Tutorial series, in which I'm going to tell you how to extend microblog with an application programming interface (or API) that clients can use to work with the application in a more direct way than the traditional w … | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XXII: Background Jobs

This is the twenty second installment of the Flask Mega-Tutorial series, in which I'm going to tell you how to create background jobs that run independently of the web server. | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XXI: User Notifications

This is the twenty first installment of the Flask Mega-Tutorial series, in which I'm going to add a private message feature, along with user notifications that appear in the navigation bar without the need to refresh the page. | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XX: Some JavaScript Magic

This is the twentieth installment of the Flask Mega-Tutorial series, in which I'm going to add a nice popup when you hover your mouse over a user's nickname. | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XIX: Deployment on Docker Containers

This is the nineteenth installment of the Flask Mega-Tutorial series, in which I'm going to deploy Microblog to the Docker container platform. | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XVI: Full-Text Search

This is the sixteenth installment of the Flask Mega-Tutorial series, in which I'm going to add a full-text search capability to Microblog.You are reading the 2024 edition of the Flask Mega-Tutorial… | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XVII: Deployment on Linux

This is the seventeenth installment of the Flask Mega-Tutorial series, in which I'm going to deploy Microblog to a Linux server.You are reading the 2024 edition of the Flask Mega-Tutorial. The… | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XVIII: Deployment on Heroku

This is the eighteenth installment of the Flask Mega-Tutorial series, in which I'm going to deploy Microblog to the Heroku cloud platform.You are reading the 2024 edition of the Flask Mega-Tutorial… | Continue reading


@blog.miguelgrinberg.com | 1 year ago

The Flask Mega-Tutorial, Part XVIII: Deployment on Heroku

This is the eighteenth installment of the Flask Mega-Tutorial series, in which I'm going to deploy Microblog to the Heroku cloud platform. | Continue reading


@blog.miguelgrinberg.com | 1 year ago

Using JavaScript-style async promises in Python

When you compare Python and JavaScript async code, you may think they are very much alike, since both use the async/await pattern. In reality, there is a significant difference between the two, which… | Continue reading


@blog.miguelgrinberg.com | 3 years ago

Optimizing Slow SQL Queries

Most database problems go unnoticed during development, because we tend to code our applications using small datasets. It is when the application has been on production for some time that database… | Continue reading


@blog.miguelgrinberg.com | 3 years ago

How to Write Unit Tests in Python, Part 1: Fizz Buzz – Miguelgrinberg.com

Today I'm starting a new series of articles about a topic that does not get a lot of coverage: how to write Python unit tests. Unlike other testing tutorials, I'm going to focus on testing techniques… | Continue reading


@blog.miguelgrinberg.com | 3 years ago

Ignore All Web Performance Benchmarks, Including This One

A couple of months ago there was an article titled Async Python is Not Faster making the rounds on social media. In it, the author Cal Paterson made the point that contrary to popular belief,… | Continue reading


@blog.miguelgrinberg.com | 4 years ago

Sync vs. Async Python: What Is the Difference?

Have you heard people say that async Python code is faster than "normal" (or sync) Python code? How can that be? In this article I'm going to try to explain what async is and how it differs from… | Continue reading


@blog.miguelgrinberg.com | 4 years ago

Video: Using Trailing Commas in Python

In this short video I comment on the benefits of using "trailing commas" when defining data structures in… | Continue reading


@blog.miguelgrinberg.com | 4 years ago

Setting Up a Flask Application in Visual Studio Code

Continue reading


@blog.miguelgrinberg.com | 5 years ago

How to Make Python Wait

Continue reading


@blog.miguelgrinberg.com | 6 years ago

The Flask Mega-Tutorial [2017 version]

Continue reading


@blog.miguelgrinberg.com | 6 years ago

The Flask Mega-Tutorial (2012)

Continue reading


@blog.miguelgrinberg.com | 6 years ago