Working notes on Python, Flask, Django, and Django REST Framework, captured while learning, not polished tutorials.
- 01/82
Big O Notation
How to analyze algorithm efficiency with Big O, common complexity classes from O(1) to O(n!), and how to read code for its time complexity.
- 02/82
Exception Handling
Using try/except to catch errors in Python, trapping specific exception types, and chaining except clauses.
- 03/82
File Handling
Opening, reading, and closing files in Python, the different modes, and the read/readline/readlines methods.
- 04/82
Consuming a REST API with requests
Fetching JSON from a REST API with the requests library, raising for bad status codes, and pulling specific keys out of the response.
- 05/82
OOP Basics
Classes, objects, and methods in Python, plus the four pillars of OOP — inheritance, encapsulation, polymorphism, and abstraction — with small runnable examples.
- 06/82
map() and filter()
Generating a new list from an existing one using map and filter, and how they differ in what they return.
- 07/82
Recursion Basics
Recursion as a self-calling function, illustrated by computing a factorial both with a loop and with recursion.
- 08/82
Reversing a String
Two ways to reverse a string in Python, slicing and recursion.
- 09/82
Flask App Context
Fixing the application-context error when running database operations from the Python terminal in a Flask app.
- 10/82
Working with Databases in Flask
Setting up Flask-SQLAlchemy, defining models, one-to-many relationships with backref, and basic CRUD from the Python shell.
- 11/82
User Registration & Login in Flask
Hashing passwords with flask-bcrypt, validating uniqueness on registration, and wiring up flask-login for sessions, logout, and route restrictions.
- 12/82
Flask Error Handlers
Registering a custom error handler for an HTTP status code in Flask.
- 13/82
Flask Blueprints
Splitting a Flask app into blueprints by feature, registering them with the app, and updating url_for calls to the blueprint-qualified route name.
- 14/82
URL Building with url_for()
Using Jinja's url_for() to build links to Flask routes, and passing extra keyword parameters through to the view function.
- 15/82
Forms with Flask-WTF
Building forms with WT-Forms, setting a secret key, handling GET/POST and validate_on_submit, flashing messages, and redirecting after submit.
- 16/82
Flask Form Validation Feedback
Showing per-field validation errors in a Bootstrap-styled Jinja template using the is-invalid class.
- 17/82
Pagination with Flask-SQLAlchemy
Using the paginate() method instead of query.all(), reading page/per_page/total, and rendering page links with iter_pages().
- 18/82
Jinja Template Inheritance
Sharing a common layout across templates with a parent template, block tags, and the extends tag.
- 19/82
Creating a Django App
Scaffolding a new Django app with startapp and registering it in INSTALLED_APPS.
- 20/82
Django Views
Writing a view function that takes a request and returns an HttpResponse.
- 21/82
Mapping URLs to Views
Creating a per-app urls.py, wiring path() to a view function, and including an app's URL configuration from the main project urls.py.
- 22/82
Using Templates in Django
Rendering HTML templates with render(), passing a context dictionary, and using Jinja-style conditionals in a template.
- 23/82
Planning Django Models
Organizing an ecommerce project's entities into apps, and why bundling everything into one monolith app is a mistake.
- 24/82
Creating Django Models
Defining model classes and field types like CharField and TextField, plus choice fields backed by a tuple list.
- 25/82
One-to-One Relationships
Defining a one-to-one relationship between two Django models with OneToOneField.
- 26/82
One-to-Many Relationships
Defining a one-to-many relationship with ForeignKey, plus a full ecommerce model set (Product, Customer, Order, Cart) showing on_delete choices.
- 27/82
Many-to-Many Relationships
Defining a many-to-many relationship between Product and Promotion with ManyToManyField.
- 28/82
Generic Relationships
The three pieces needed for a generic relationship in Django — Content Type, Object Id, and Content Object — with Tag and Like examples.
- 29/82
Django Migrations
Creating and running migrations to keep the database schema in sync with your models.
- 30/82
Customizing the Database Schema
Adding indexes and a custom table name to a model via its Meta subclass.
- 31/82
Using MySQL in Django
Switching the database engine from the default SQLite to MySQL in settings.py.
- 32/82
Running Custom SQL in a Migration
Creating an empty migration and using RunSQL to run arbitrary SQL, with a matching reverse operation.
- 33/82
Managers and QuerySets
Why Product.objects returns a manager, why querysets are lazy, and how chaining filter()/order_by() builds up a query before it's evaluated.
- 34/82
Retrieving Objects
Using .all() and .get(), and safer alternatives to try/except for handling missing objects with filter().first() and .exists().
- 35/82
Filtering Objects
Lookup types like __gt, __range, and __contains, filtering across relationships, and case-insensitive string lookups.
- 36/82
Q Objects for Complex Filtering
Combining filter conditions with OR/AND/AND-NOT using Q objects and the bitwise |, &, and &~ operators.
- 37/82
F Objects for Referencing Fields
Comparing one model field to another within a filter using F objects, including referencing fields across relationships.
- 38/82
Sorting Data
Sorting a queryset with order_by(), reversing direction, sorting by multiple fields, and the earliest()/latest() shortcuts.
- 39/82
Limiting Results
Paging through a large queryset using Python's array slicing syntax.
- 40/82
Selecting Specific Fields
Restricting a query to specific columns with values(), values_list(), only(), and its opposite defer().
- 41/82
Aggregating Data
Computing counts, sums, and averages over a queryset with the aggregate() method.
- 42/82
Annotating Objects
Adding computed attributes to query results with the annotate() method.
- 43/82
Creating Objects
Inserting a new row by instantiating a model, setting attributes, and calling save(), plus the shorthand objects.create().
- 44/82
Updating Objects
Why a naive save() can wipe out fields you didn't mean to touch, and safer alternatives — read-before-update and the queryset update() method.
- 45/82
Deleting Objects
Deleting a single object with delete(), and deleting a whole queryset at once.
- 46/82
Database Transactions
Wrapping related saves in @transaction.atomic() (or a with block) so an Order and its OrderItems either both save or neither does.
- 47/82
The Django Admin Site
Creating a superuser and customizing the admin site's header and index title.
- 48/82
Registering Models with the Admin
Registering a model with admin.site.register(), and adding a __str__ method and Meta ordering so it displays sensibly.
- 49/82
Customizing the Admin List Page
Using a ModelAdmin subclass to control list_display, list_editable, list_per_page, and ordering on the admin change list.
- 50/82
Getting Started with DRF
Installing Django REST Framework and adding it to INSTALLED_APPS.
- 51/82
Creating API Views
Wrapping a plain Django view with @api_view to get DRF's Request/Response classes and a browsable API, plus URL converters for path parameters.
- 52/82
Creating Serializers
Converting model instances into dictionaries with a Serializer class, handling missing objects, and serializing a whole queryset with many=True.
- 53/82
Custom Serializer Fields
Adding a computed field to a serializer that isn't present on the underlying model, using SerializerMethodField.
- 54/82
Serializing Relationships
Four ways to represent a related object in a serializer — PrimaryKeyRelatedField, StringRelatedField, a nested serializer, and HyperlinkedRelatedField.
- 55/82
Model Serializers
Removing duplication between a model and its serializer by using ModelSerializer with a Meta class.
- 56/82
Deserializing Data
Turning incoming POST data back into a model instance, validating it, and returning a 400 with error details when it's invalid.
- 57/82
Saving Objects with a Serializer
Using serializer.save() to create/update, and overriding create() and update() for custom logic.
- 58/82
Updating Objects via a View
Handling PUT requests in a view function by passing an existing instance plus new data into the serializer.
- 59/82
Deleting Objects via a View
Adding a DELETE branch to a detail view function.
- 60/82
Class-Based Views
Rewriting function-based views as APIView subclasses with get/post/put/delete methods.
- 61/82
Mixins
How ListModelMixin and CreateModelMixin encapsulate the repeated list/create pattern shared by different views.
- 62/82
Generic Views
Using ListCreateAPIView, a concrete class that already combines ListModelMixin and CreateModelMixin, instead of wiring mixins by hand.
- 63/82
Customizing Generic Views
Switching a detail view to RetrieveUpdateDestroyAPIView and overriding just the delete method for app-specific logic.
- 64/82
ViewSets
Combining a list view and a detail view into a single ModelViewSet, and using ReadOnlyModelViewSet for read-only resources.
- 65/82
Routers
Registering viewsets with SimpleRouter or DefaultRouter instead of hand-writing urlpatterns for each one.
- 66/82
Nested Routers
Using drf-nested-routers to build a reviews-under-products endpoint with NestedDefaultRouter.
- 67/82
Filtering a ViewSet by Query Param
Overriding get_queryset() on a viewset to filter by a query string parameter like collection_id.
- 68/82
Generic Filtering with django-filter
Replacing hand-rolled query-param filtering with DjangoFilterBackend and a FilterSet class that supports range lookups.
- 69/82
Searching
Adding text-based search across multiple fields with SearchFilter.
- 70/82
Sorting Fields
Letting clients sort results by specific fields with OrderingFilter.
- 71/82
Pagination
Setting PageNumberPagination per-view or globally, and creating a reusable pagination class to silence DRF's page-size warning.
- 72/82
Extending the User Model
Why you'd extend Django's built-in User model (e.g. to make email unique), and the migration/errors that come with doing it mid-project.
- 73/82
Authentication with Djoser
Using Djoser to get a ready-made authentication API on top of Django, choosing JWT over token-based auth, and the endpoints it provides.
- 74/82
Registering New Users
Customizing Djoser's user-creation serializer to include first/last name.
- 75/82
Building the Profile API
A CustomerViewSet built from CreateModelMixin, RetrieveModelMixin, and UpdateModelMixin since Djoser doesn't cover profile endpoints.
- 76/82
Logging In with JWT
The access/refresh token lifecycle with djoser + simplejwt, and how to override their default lifetimes.
- 77/82
Getting the Current User
Hitting /auth/users/me with a bearer token, and customizing which fields Djoser returns for the current user.
- 78/82
Permissions
Restricting endpoints with IsAuthenticated, per-action permissions via get_permissions(), and a custom IsAdminOrReadOnly permission class.
- 79/82
Serving Images
Configuring MEDIA_URL/MEDIA_ROOT and serving uploaded media files in development.
- 80/82
Adding Images to Products
A ProductImage model with a one-to-many relationship to Product, using ImageField and Pillow.
- 81/82
File Validation
Writing a custom validator to cap uploaded file size, and validating file extensions with FileExtensionValidator.
- 82/82
Sending Emails
Running a local SMTP4dev server for dev email testing, the available Django email backends, and using send_mail/mail_admins.