
This course includes our updated coding exercises so you can practice your skills as you learn.
See a demo
This course is structured in a specific way to make it as easy as possible for you to get exactly what you want out of it.
This lecture looks at maximising your time's value by making the course as efficient as possible for you.
Installing Python is very simple! Follow these steps and you'll be up and running in no time.
Installing Python is very simple! Follow these steps and you'll be up and running in no time.
This is a short introductory video to this section. I'm really excited to guide you through this Python refresher course!
This lecture has a link to all the Python code we'll write in this section. Use it to check your code as you write it, or to refresh your memory!
Let's look at variables in Python. Variables are just names for values, which we can reuse and reset.
Python is a dynamic typed language, which means variables don't need be constrained to a specific type.
The solution to the "Variables" Python coding exercise.
Master string formatting in Python 3.6 or later by using f-strings to embed variables and print dynamic greetings. Compare with templates via format to reuse strings with placeholders.
Learn how to get user input in Python, convert strings to numbers, and format results with f-strings, including handling square feet and square metres.
Launch your first Python app by building an age-to-days converter with user input and an f-string, and verify it with tests in a lab workflow.
In this lecture we look at three essential data structures in Python: lists, tuples, and sets.
A list is an ordered collection of items.
A tuple is an immutable ordered collection of items.
A set is an unordered collection of unique items.
In this fascinating video, we look at advanced set operations: calculating items which are in two sets, or items which are in one set but not another.
The solution to the "Lists, tuples, and sets" Python coding exercise.
Explore booleans in Python to drive decisions with boolean logic, using comparisons like ==, !=, >, <, >=, <=, and understand is versus equality across lists, strings, and more.
This video explores how to create programs which can change depending on some input. For example, we might ask the user if they want to continue or not.
This makes use of boolean comparisons, such as:
The boolean comparisons we have available in Python are many:
Explore how the in keyword checks membership across lists, tuples, sets, and strings, with examples of true/false results and using sets to prevent duplicates.
Learn how the in keyword works in if statements by testing input against a set of watched movies. Build a magic number app with input handling and conditional logic.
Loops allow us to repeat things over and over. This video explores two different types of loop in Python: for loop and while loop.
The solution to the "Flow control" Python coding exercise.
List comprehension is a relatively unique thing to Python.
It allows us to succinctly use a for loop inside a list to generate values. These values then end up in the list.
For example, [x for x in range(10)] generates a list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
Dictionaries are an extremely useful thing in Python.
They are akin to sets, but instead of being a set of unique values, they are a set of unique keys, and each has a value associated with it.
Explore destructuring variables in Python to unpack tuples and dictionary items into individual values, use in for-loops, handle missing data, ignore parts with underscores, and apply head and tail patterns.
In this video, let's look at methods in Python by creating some examples. Creating methods is simple, you just need the one keyword: def.
Explore function arguments and parameters in Python, distinguishing positional and keyword arguments, with examples like add, say hello, and divide.
Define default parameter values in Python by making y optional with a default, while x stays required; defaults must come after required parameters, avoiding positional arguments after keyword.
Learn how functions return values in Python, distinguishing print from return and None as a default. See add and divide examples to understand how return values drive outcomes.
The solution to the "Method" Python coding exercise.
Explore lambda functions in Python, anonymous one-line helpers that take inputs and return outputs, and compare them to named functions, list comprehensions, and map usage.
Learn to build a username-to-user mapping with a dictionary comprehension in Python, converting a list of user tuples into a dictionary and using it for login authentication.
The solution to the "Dictionaries and students" Python coding exercise.
*args and **kwargs are truly fascinatingly confusing. For eons, they have annoyed Python learners.
To this I say no more!
They're just a way of passing arguments.
Learn how to unpack keyword arguments in Python using **kwargs and dictionaries, and how to pass and unpack named arguments into and from functions.
Objects are the natural progression from dictionaries. Instead of just holding data, objects hold another special type of data: methods.
A method is a function which operates on the object calling it. Thus, an object can use its own values to calculate outputs of methods. Very cool.
Learn how Python's magic methods __str__ and __repr__ control string representations of objects, enabling readable output for users and unambiguous recreation of objects in debugging.
The solution to the "Classes and objects" Python coding exercise.
In many instances, we don't want our methods to be solely referencing the object which calls them. Sometimes, we want to reference the class of the object. Other times, we don't need either the object or the class.
@classmethod and @staticmethod are two decorators (looking at that shortly!) which extend the capabilities of methods.
The solution to the "@classmethod and @staticmethod" Python coding exercise.
Classes in Python can also inherit from one another. This essentially means that a class contains all of the properties and methods of the class it inherits from—but with the added bonus that it can have more.
Learn class composition in Python by building a bookshelf that has many books, illustrating why composition is preferred over inheritance and that a book is not a bookshelf.
Discover how type hints in Python 3.5+ specify inputs and returns, with examples like a list average function returning a float and using the typing module.
Explore imports in Python, from x import y versus import x, and how __name__ changes between run and import. Understand sys.path, PYTHONPATH, and module caching via sys.modules.
Explore how relative imports in Python differ from absolute imports, why they require a package structure, how dot notation works, and why the lecturer recommends using absolute imports for simplicity.
Learn how Python handles errors by raising ZeroDivisionError and using try-except blocks to catch and customize messages. Explore else and finally clauses for robust error handling and clean-up.
Explore custom error classes in Python with a book model with name, page count, and pages read, and a too many pages read error inheriting from value error.
Not only we can pass values from one method to another, but we can also pass functions.
This is not used very often, but it can sometimes yield very powerful methods in very few lines of code.
One of the most confusing aspects of Python for learners is the concept of decorators.
These are things we can place on top of function definitions which allow us to extend the function by executing code before and after the function.
They are extremely powerful when used well!
Learn how the at syntax decorates a function with make secure, wrapping get admin password, and how functools.wraps preserves the original name and docs.
Learn how to decorate functions with parameters by making decorators accept unlimited arguments using *args and **kwargs, enabling flexible use across different functions.
In this video we look at advanced decorators in Python, which is decorators that take arguments.
This amplifies the decorator's usefulness, although also makes them slightly more contrived.
Explore mutability in Python by seeing how list names reference the same object, how appending to one updates both, and how tuples and numbers remain immutable.
Discover why mutable default parameters are a bad idea in Python, learn how shared lists across instances occur, and adopt the None pattern to safely initialize optional lists.
Build your first rest API with Flask and Python to create stores and items via post and retrieve them via get to /store and /store/{name}.
Set up a Flask REST API project by creating a Python virtual environment, selecting the interpreter, installing Flask, and running a basic app in app.py to expose endpoints.
Create your first rest api endpoint with Flask, returning a Python list of stores and items as json at /store. Open 127.0.0.1:5000 to view the data.
Explore how JSON serves as the text-based data exchange used by REST APIs, outlining keys, values, strings, numbers, booleans, lists, and nested objects, plus serialization and prettified versus non-prettified formats.
Learn how to test your REST API by sending requests with the Insomnia REST client (or Postman), inspect responses, and verify endpoints through manual exploratory testing.
Create stores in a Flask REST API by posting JSON to /store, parse request, append a new store with name and items, and return the created store with status 201.
Create items in a specific store using a dynamic Flask URL. Post JSON with name and price, append to the matched store, and return the new item with 201 status.
Learn how to fetch a specific store and its items using Flask get endpoints, /store/name and /store/name/item, returning dictionaries and json for flexible data handling.
Compare Docker containers with virtual machines and learn how Docker images and Dockerfiles create lightweight Linux-based environments to run Python apps like Flask, using pip.
Build a Docker image for a Flask app and run it as a container with port forwarding from 5005 to 5000 using a Dockerfile and docker run.
Learn to run a flask rest api with docker compose by defining a docker-compose.yml, map port 5000 to the container, and sync code with volumes for easy, reliable starts.
Debug flask apps in docker with VS Code by using breakpoints and inspecting requests. Overcome docker limitations with a docker compose debug workflow and debugpy on port 5678.
Learn to refactor the API by replacing name identifiers with unique IDs, store and item data in dictionaries, and expose endpoints using store_id and item_id for efficient access.
Enhance our api with flask-smorest abort to standardize error handling and return json messages for not found (404) and bad request (400) scenarios.
Add and organize endpoints for items and stores in a Flask-based rest api, including get, create, update, and delete operations, with proper error handling and project structure.
Learn to run a Flask REST API in Docker with automatic reloading, using a separate requirements.txt for caching, and optional volume syncing for development versus deployment.
Learn to build a Flask REST API using flask-smorest blueprints and MethodView, register endpoints for stores and items, and explore swagger-ui documentation for API testing.
Learn to implement marshmallow schemas for API validation, defining item and store schemas with required and dump_only fields to validate incoming data and shape outgoing responses.
Validate incoming client data with marshmallow schemas, including item, item update, and store schemas. Use @blp.arguments to receive validated fields and improve swagger UI documentation.
Decorate Flask-Smorest responses with Marshmallow schemas to filter fields, cast data, and define status codes, while generating documentation for items and stores.
Replace the in-code data with a relational database using SQLAlchemy and Flask-SQLAlchemy, an ORM offering multithreading, automatic table creation, migrations, and cleaner code.
Learn to code a simple SQLAlchemy model by creating item and store models, defining __tablename__ and columns (id, name, price, store_id), and mapping rows to Python objects.
Explains one-to-many relationships in SQLAlchemy using store_id as a foreign key, defines relationships and back_populates, discusses lazy loading, and refactors schemas into plain and nested variants.
Configure Flask-SQLAlchemy in a factory-created app, import models, and auto-create tables with db.create_all using an environment-aware database URL (SQLite for development, PostgresSQL later).
learn how to insert items into a database using SQLAlchemy in a Flask app, create item models, convert data to keyword arguments, add and commit, and handle SQLAlchemy integrity errors.
Retrieve an item or store by primary key using get_or_404, which returns 404 if not found, and serialize the result to json with the corresponding schema.
learn how to implement idempotent put requests with SQLAlchemy by updating existing items or creating new ones, using store_id and item_data to ensure a consistent end state.
Retrieve the full list of models by calling ItemModel.query.all, convert with ItemSchema many=true into a list of items, then repeat for StoreModel.query.all and verify with Insomnia.
Learn how to delete models with SQLAlchemy in a Flask rest api by removing stores and items, committing changes, and returning a 200 status code and messages.
Learn how cascades in SQLAlchemy handle deleting a store and its items, contrasting SQLite's missing foreign key constraints with PostgreSQL, and using cascade is all and delete to remove children.
Conclude the section by reviewing SQLAlchemy-based APIs with SQLite testing, implementing ItemModel and store relationships, marshmallow schemas, and session usage, and note many-to-many relationships and Postgres readiness.
Explore many-to-many relationships between items and tags within stores using SQLAlchemy, and implement rest APIs to create, list, link, unlink, and manage tags per store.
Explore the one-to-many relationship between stores and tags in a Flask and Python REST API, modeling TagModel with a store_id foreign key, configuring lazy dynamic relationships, and building tag endpoints.
Implement many-to-many relationships between items and tags using a secondary table with item_id and tag_id foreign keys, wiring SQLAlchemy relationships and endpoints to link, unlink, and delete tags.
Learn how jwt-based access tokens authenticate api requests, issuing tokens containing user IDs via /login, and using /my-info to personalize responses, with expiry times and refreshing.
Set up Flask JWT Extended, install dependencies, and initialize JWTManager with a secret key for signing and verifying JWTs—generate a secure key with the secrets module for deployment.
Define the user model and schema with SQLAlchemy. Create UserModel with id, username (unique), and password (nonnullable, not unique); configure UserSchema with dump_only id and load_only password, and initialize table.
Register users with a post /register endpoint, hashing passwords using pbkdf2_sha256 before storage, and verify via get and delete by user id for testing, with dockerized Flask setup.
Create a /login endpoint that authenticates a user by verifying the password with pbkdf2_sha256, returns a jwt access token containing the user id, and uses it to access endpoints.
Protect endpoints by applying the jwt_required decorator to require a jwt obtained after login and sent in the authorization header as bearer.
Explore how to add and use JWT claims with Flask, using additional_claims_loader to embed admin status in tokens, and enforce admin-only access in endpoints with get_jwt and authorization headers.
Learn to log out users in a Flask REST API by using a blocklist of JWTs (JTI) and a logout endpoint, with token revocation checks.
Learn to streamline insomnia testing by extracting the bearer token from the login response with jsonpath and environment variables for reuse across endpoints.
Implement token refreshing with Flask-JWT-Extended by issuing access and refresh tokens at login. Refresh non-fresh tokens via the /refresh endpoint and require fresh tokens for sensitive actions.
Install flask-migrate and add it to your requirements, then configure migrate in app.py after db.init_app to enable alembic migrations.
Initialize your sqlite database with flask-migrate by creating migrations, generating the first migration, and applying it to build stores, users, items, tags, and items_tags tables; Alembic tracks revisions.
Learn to modify a SQLAlchemy model and add a description column to the items table, then generate and apply a migration with Alembic and Flask-Migrate.
Review and manually modify database migrations in Alembic to ensure new columns with defaults populate existing rows, using nullable true and op.execute sql to set values, and verify downgrade.
Learn how git repositories organize a project into working, staging, and committed areas, create commits as snapshots, and collaborate by pushing changes to remote repositories.
Initialize a git repository with git init and track changes with git add and git commit. Use .gitignore to exclude .venv and __pycache__ so only essential files are committed.
Master Markdown basics for writing text that renders in commit messages, GitHub issues, and documents, including headings, code blocks, block quotes, lists, links, and images.
Learn how to work with remote repositories, link a local project to a remote on GitHub or alternatives like GitLab or Bitbucket, push commits, and collaborate securely.
Learn how git branches map to commits, switch between main and other branches with checkout, and merge changes while managing head and detached head risks and potential conflicts.
Resolve merge conflicts in git by examining main and feature branches in app.py, recognizing conflict markers, and choosing between keep theirs, keep ours, or manual edits to complete the merge.
Learn about the final e-book chapters, including how git stash saves your working changes, and how to work with GitHub, forks, pull requests, and issues for open source contributions.
Are you tired of boring, outdated, incomplete, or incorrect tutorials? I say no more to copy-pasting code that you don’t understand.
Welcome to the bestselling REST API course on Udemy! I'm Jose. I'm a software engineer, here to help you truly understand and develop your skills in web and REST API development with Python, Flask, and Docker.
Production-ready REST APIs with Flask
This course will guide you in creating simple, intermediate, and advanced REST APIs including authentication, deployments, databases, and much more.
We'll start with a Python refresher that will take you from the very basics to some of the most advanced features of Python—that's all the Python you need to complete the course.
Using Flask and popular extensions Flask-Smorest, Flask-JWT-Extended, and Flask-SQLAlchemy we will dive right into developing complete, solid, production-ready REST APIs.
We will also look into essential technologies like Git and database migrations with Alembic.
You'll be able to...
Create resource-based, production-ready REST APIs using Python, Flask, and popular Flask extensions;
Handle secure user registration and authentication with Flask.
Using SQLAlchemy and Flask-SQLAlchemy to easily and efficiently store resources to a database; and
Understand the complex intricacies of deployments of Flask REST APIs.
Use Docker to simplify running and deploying your REST APIs.
But what is a REST API anyway?
A REST API is an application that accepts data from clients and returns data back. For example, a REST API could accept text data from the client, such as a username and password, and return whether that is a valid user in the database.
When developing REST APIs, our clients are usually web apps or mobile apps. That's in contrast to when we make websites, where the clients are usually the users themselves.
Together we'll develop a REST API that not only allows clients to authenticate but also to store and retrieve any data you want from a database. Learning this will help you develop any REST API that you need for your own projects!
I pride myself on providing excellent support and feedback to every single student. I am always available to guide you and answer your questions.
I'll see you on the inside. Take your first step towards REST API mastery!