python
48 lines · 8 steps
How a Flask blueprint validates and creates users
A Flask blueprint pairs a Marshmallow schema with a POST route to validate input, reject duplicates, and persist a new user.
Explained by
highlit
1from flask import Blueprint, request, jsonify
2from marshmallow import Schema, fields, validate, ValidationError, EXCLUDE
3
4from .models import db, User
5from .services import send_welcome_email
6
7bp = Blueprint("users", __name__, url_prefix="/api/users")
8
9
10class CreateUserSchema(Schema):
11 class Meta:
12 unknown = EXCLUDE
13
14 email = fields.Email(required=True)
15 username = fields.Str(
16 required=True,
17 validate=validate.Length(min=3, max=32),
18 )
19 password = fields.Str(
20 required=True,
21 load_only=True,
22 validate=validate.Length(min=8),
23 )
24 age = fields.Int(validate=validate.Range(min=13, max=120))
25
26
27create_user_schema = CreateUserSchema()
28
29
30@bp.post("")
31def create_user():
32 try:
33 data = create_user_schema.load(request.get_json(force=True))
34 except ValidationError as err:
35 return jsonify(errors=err.messages), 422
36
37 if User.query.filter_by(email=data["email"]).first():
38 return jsonify(errors={"email": ["already registered"]}), 409
39
40 user = User(email=data["email"], username=data["username"], age=data.get("age"))
41 user.set_password(data["password"])
42
43 db.session.add(user)
44 db.session.commit()
45
46 send_welcome_email.delay(user.id)
47
48 return jsonify(id=user.id, email=user.email, username=user.username), 201
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Validating request bodies with a schema keeps parsing, type coercion, and error handling out of your route logic.
- 2Checking for existing records before insert lets you return a meaningful conflict status instead of a database error.
- 3Offloading side effects like emails to a background task keeps the request path fast and responsive.
Related explainers
python
import logging import uuid from contextvars import ContextVar
Request ID tracing in FastAPI middleware
middleware
context-variables
request-tracing
Intermediate
7 steps
ruby
require "phonelib" class PhoneNumber class InvalidNumber < StandardError; end
Wrapping phone parsing in a Ruby value object
value-object
memoization
validation
Intermediate
7 steps
typescript
import { Component } from '@angular/core'; import { NgForm } from '@angular/forms'; interface SignupModel {
How template-driven forms validate in Angular
forms
two-way-binding
validation
Intermediate
9 steps
python
import json import time import queue
Server-Sent Events streaming in Flask
server-sent-events
streaming
pub-sub
Advanced
9 steps
python
import random import click from faker import Faker
Building a Flask seed command with Click
cli
database seeding
orm
Intermediate
7 steps
python
import smtplib from email.message import EmailMessage from threading import Thread
Sending welcome emails off the request thread in Flask
background-threads
app-context
email
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/how-a-flask-blueprint-validates-and-creates-users-explained-python-7386/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.