Introduction to Django

  1. What Is Django?



  2. MVT Architecture (Model–View–Template)

  3. Django Term Role Equivalent in MVC
    Model Data representation and database interaction Model
    View Business logic and request handling Controller
    Template HTML presentation layer View


  4. Installing Django

  5. pip install django
    
    django-admin --version
    


  6. Create a Django Project

  7. django-admin startproject mysite
    cd mysite
    
    mysite/
    ├── manage.py
    └── mysite/
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        ├── asgi.py
        └── wsgi.py
    


  8. Running the Development Server

  9. python manage.py runserver
    


  10. Create Your First App

  11. python manage.py startapp blog
    
    blog/
    ├── admin.py
    ├── apps.py
    ├── models.py
    ├── tests.py
    ├── views.py
    └── migrations/
    


  12. Defining a Model (Database Layer)

  13. # blog/models.py
    
    from django.db import models
    
    class Post(models.Model):
        title = models.CharField(max_length=200)
        body = models.TextField()
        created_at = models.DateTimeField(auto_now_add=True)
    
    python manage.py makemigrations
    python manage.py migrate
    


  14. Creating a View (Business Logic)

  15. # blog/views.py
    
    from django.http import HttpResponse
    
    def hello(request):
        return HttpResponse("Hello, Django!")
    


  16. URL Routing

  17. # blog/urls.py
    
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path("hello/", views.hello),
    ]
    
    # mysite/urls.py
    
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("blog/", include("blog.urls")),
    ]
    


  18. Django Template System

  19. <!-- blog/templates/blog/home.html -->
    <h1>Welcome to My Blog</h1>
    <p>This is rendered from a Django template.</p>
    
    # blog/views.py
    
    from django.shortcuts import render
    
    def home(request):
        return render(request, "blog/home.html")
    


  20. The Django Admin

  21. # blog/admin.py
    
    from django.contrib import admin
    from .models import Post
    
    admin.site.register(Post)
    
    python manage.py createsuperuser
    


  22. Django ORM: Querying the Database

  23. from blog.models import Post
    
    # Create
    Post.objects.create(title="Hello", body="Content here")
    
    # Read
    posts = Post.objects.all()
    
    # Filter
    latest = Post.objects.filter(title__icontains="hello")
    


  24. Common Django Features (Built-In)

  25. Feature Description Example
    Authentication User accounts, login, permissions from django.contrib.auth.models import User
    Admin Automatic admin site /admin/
    ORM Database abstraction Model.objects.filter(...)
    Templates HTML rendering system render(request, "home.html")
    Forms Built-in HTML form processing & validation forms.Form
    Security Middleware CSRF, XSS protection, secure cookies django.middleware.csrf.CsrfViewMiddleware


  26. Summary




Project vs App in Django

  1. Beginners are often confused by the difference between Django Project and Django App


  2. What Is a Django Project?

  3. python3 -m django startproject mysite
    
    mysite/
    ├── manage.py
    └── mysite/
        ├── __init__.py
        ├── settings.py      # Global Django settings (DEBUG, DB, middleware, etc.)
        ├── urls.py          # Root URL dispatcher
        ├── wsgi.py          # For production servers
        └── asgi.py          # For async servers
    


  4. What Is a Django App?

  5. python3 manage.py startapp blog
    
    blog/
    ├── admin.py        # Admin interface setup
    ├── apps.py         # App configuration class
    ├── models.py       # Database models
    ├── views.py        # Request handlers (Controller logic)
    ├── tests.py        # Unit tests
    └── migrations/     # Database migrations
    


  6. Project vs App — Conceptual Difference

  7. Aspect Django Project Django App
    Purpose Overall configuration and container Specific feature or module
    Number One per website Many per project
    Reusable? No Yes, apps can be placed on PyPI
    Created by startproject startapp
    Main Files settings.py, urls.py models.py, views.py, admin.py
    Scope Entire website Narrow, focused feature


  8. When Should You Create a New App?



  9. How an App Integrates Into a Project

  10. # mysite/settings.py
    
    INSTALLED_APPS = [
        "django.contrib.admin",
        "django.contrib.auth",
        "django.contrib.contenttypes",
        "django.contrib.sessions",
        "django.contrib.messages",
        "django.contrib.staticfiles",
        "blog",   # your new app
    ]
    


  11. Example: One Project, Multiple Apps

  12. mysite/
    ├── accounts/      # login, signup, profiles
    ├── posts/         # uploading + viewing posts
    ├── comments/      # comments on posts
    ├── notifications/ # user notifications
    └── messages/      # direct messaging
    


  13. Summary




manage.py in Django

  1. What Is manage.py?



  2. Creating a Project and Seeing manage.py

  3. python3 -m venv .venv
    source .venv/bin/activate
    python3 -m pip install django
    
    python3 -m django startproject mysite
    cd mysite
    
    mysite/
    ├── manage.py
    └── mysite/
        ├── __init__.py
        ├── asgi.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py
    


  4. How manage.py Works Internally?

  5. #!/usr/bin/env python3
    import os
    import sys
    
    def main():
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
        from django.core.management import execute_from_command_line
        execute_from_command_line(sys.argv)
    
    if __name__ == "__main__":
        main()
    


  6. Basic Usage Pattern

  7. # Always inside the virtual environment
    source .venv/bin/activate
    
    # Basic pattern:
    python3 manage.py <command> [options]
    


  8. Frequently Used manage.py Commands

  9. Command Usage Description
    runserver python3 manage.py runserver Start the development server.
    startapp python3 manage.py startapp blog Create a new Django app inside the project.
    makemigrations python3 manage.py makemigrations Generate migration files from model changes.
    migrate python3 manage.py migrate Apply migrations to the database.
    createsuperuser python3 manage.py createsuperuser Create an admin user for the Django admin site.
    shell python3 manage.py shell Open a Python shell with Django loaded.
    test python3 manage.py test Run your test suite.
    showmigrations python3 manage.py showmigrations List migrations and their applied status.
    sqlmigrate python3 manage.py sqlmigrate app_name 0001 Show the raw SQL for a migration.
    check python3 manage.py check Run Django's system checks for common configuration issues.


  10. Running the Development Server

  11. python3 manage.py runserver
    
    python3 manage.py runserver 8080
    


  12. Creating Apps with manage.py

  13. python3 manage.py startapp blog
    
    blog/
    ├── admin.py
    ├── apps.py
    ├── models.py
    ├── tests.py
    ├── views.py
    └── migrations/
    


  14. Managing Database Schema: makemigrations and migrate

  15. # Generate migration files
    python3 manage.py makemigrations
    
    # Apply them to the database
    python3 manage.py migrate
    


  16. Admin User and Auth Management

  17. python3 manage.py createsuperuser
    


  18. Django Shell for Interactive Work

  19. python3 manage.py shell
    
    from blog.models import Post
    
    Post.objects.create(title="Hello", body="From the shell")
    print(Post.objects.all())
    


  20. manage.py vs django-admin



  21. Summary




Basic Django Settings

  1. What Are Django Settings?



  2. Location of Settings

  3. python3 -m venv .venv
    source .venv/bin/activate
    python3 -m pip install django
    
    python3 -m django startproject mysite
    cd mysite
    
    mysite/
    ├── manage.py
    └── mysite/
        ├── __init__.py
        ├── settings.py   <-- settings file
        ├── urls.py
        ├── asgi.py
        └── wsgi.py
    


  4. Important Settings in settings.py

    1. DEBUG

    2. DEBUG = True
      
      DEBUG = False
      


    3. SECRET_KEY

    4. SECRET_KEY = "django-insecure-abcd1234..."
      


    5. ALLOWED_HOSTS

    6. ALLOWED_HOSTS = ["127.0.0.1", "localhost"]
      
      ALLOWED_HOSTS = ["mywebsite.com"]
      


    7. INSTALLED_APPS

    8. INSTALLED_APPS = [
          "django.contrib.admin",
          "django.contrib.auth",
          "django.contrib.contenttypes",
          "django.contrib.sessions",
          "django.contrib.messages",
          "django.contrib.staticfiles",
          "blog",   # your app
      ]
      


    9. MIDDLEWARE

    10. MIDDLEWARE = [
          "django.middleware.security.SecurityMiddleware",
          "django.contrib.sessions.middleware.SessionMiddleware",
          "django.middleware.common.CommonMiddleware",
          "django.middleware.csrf.CsrfViewMiddleware",
          "django.contrib.auth.middleware.AuthenticationMiddleware",
          "django.contrib.messages.middleware.MessageMiddleware",
      ]
      


    11. ROOT_URLCONF

    12. ROOT_URLCONF = "mysite.urls"
      


    13. TEMPLATES

    14. TEMPLATES = [
          {
              "BACKEND": "django.template.backends.django.DjangoTemplates",
              "DIRS": [],
              "APP_DIRS": True,
              "OPTIONS": {
                  "context_processors": [
                      "django.template.context_processors.debug",
                      "django.template.context_processors.request",
                      "django.contrib.auth.context_processors.auth",
                      "django.contrib.messages.context_processors.messages",
                  ],
              },
          },
      ]
      


    15. DATABASES

    16. DATABASES = {
          "default": {
              "ENGINE": "django.db.backends.sqlite3",
              "NAME": BASE_DIR / "db.sqlite3",
          }
      }
      
      DATABASES = {
          "default": {
              "ENGINE": "django.db.backends.postgresql",
              "NAME": "mydb",
              "USER": "myuser",
              "PASSWORD": "mypassword",
              "HOST": "localhost",
              "PORT": "5432",
          }
      }
      


    17. AUTH_PASSWORD_VALIDATORS

    18. AUTH_PASSWORD_VALIDATORS = [
          {"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
          {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
          {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
          {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
      ]
      


    19. STATIC_URL and STATICFILES_DIRS

    20. STATIC_URL = "/static/"
      STATICFILES_DIRS = [
          BASE_DIR / "static",
      ]
      


    21. TIME_ZONE and LANGUAGE_CODE

    22. LANGUAGE_CODE = "en-us"
      TIME_ZONE = "UTC"
      USE_TZ = True
      



URL Routing with urls.py in Django

  1. Django uses a URL Routing System to Map Incoming Browser Requests to Specific View Functions



  2. Default Project-Level urls.py

  3. # mysite/urls.py
    
    from django.contrib import admin
    from django.urls import path
    
    urlpatterns = [
        path("admin/", admin.site.urls),
    ]
    


  4. Adding Routes in Project-Level urls.py

  5. # blog/views.py
    
    from django.http import HttpResponse
    
    def hello(request):
        return HttpResponse("Hello from blog!")
    
    # mysite/urls.py
    
    from django.contrib import admin
    from django.urls import path
    from blog.views import hello
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("hello/", hello),
    ]
    


  6. Using Application-Level urls.py (Recommended)

  7. blog/
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── models.py
    ├── views.py
    └── urls.py   <-- create this file
    
    # blog/urls.py
    
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path("hello/", views.hello),
    ]
    
    # mysite/urls.py
    
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("blog/", include("blog.urls")),
    ]
    


  8. Understanding the path() Syntax

  9. path("hello/", views.hello, name="hello")
    


  10. URL Parameters and Converters

  11. path("post/<int:id>/", views.show_post)
    

    def show_post(request, id):
        return HttpResponse(f"Post ID is {id}")
    


  12. Using include() to Organize URL Structures

  13. urlpatterns = [
        path("blog/", include("blog.urls")),
        path("shop/", include("shop.urls")),
        path("api/", include("api.urls")),
    ]
    


  14. Named URLs (Highly Recommended)

  15. path("hello/", views.hello, name="hello")
    
    from django.urls import reverse
    reverse("hello")   # returns "/hello/"
    
    <a href="{% url 'hello' %}">Say Hello</a>
    


  16. Using URL Namespaces

  17. # blog/urls.py
    
    app_name = "blog"
    
    urlpatterns = [
        path("hello/", views.hello, name="hello"),
    ]
    
    {% url 'blog:hello' %}


Understanding wsgi.py in Django

  1. What Is WSGI?



  2. Where Is wsgi.py Located?

  3. mysite/
    ├── manage.py
    └── mysite/
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        ├── wsgi.py      <-- here!
        └── asgi.py
    


  4. What Does wsgi.py Contain?

  5. # mysite/wsgi.py
    
    import os
    from django.core.wsgi import get_wsgi_application
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
    
    application = get_wsgi_application()
    


  6. Why Do We Need wsgi.py?



  7. Relationship Between manage.py and wsgi.py



  8. Running Django in Production With WSGI

  9. python3 -m venv .venv
    source .venv/bin/activate
    python3 -m pip install gunicorn
    gunicorn mysite.wsgi:application
    


  10. How WSGI Processes a Request (Step-by-Step)

    1. Browser sends an HTTP request → web server receives it
    2. Web server calls your WSGI application object
    3. wsgi.py gives Django the request
    4. Django:
      • loads URL configuration
      • dispatches to the correct view
      • produces an HttpResponse
    5. Response is passed back through WSGI to the server
    6. Server sends response to the browser


  11. WSGI vs. ASGI

  12. Interface Purpose Typical Server
    WSGI Traditional synchronous web apps Gunicorn, uWSGI, mod_wsgi
    ASGI Async features (WebSockets, HTTP/2) Uvicorn, Daphne



  13. Do You Ever Edit wsgi.py?




Understanding asgi.py in Django

  1. What Is ASGI?



  2. Where Is asgi.py Located?

  3. mysite/
    ├── manage.py
    └── mysite/
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        ├── asgi.py      <-- here!
        └── wsgi.py
    


  4. The Default asgi.py File

  5. # mysite/asgi.py
    
    import os
    from django.core.asgi import get_asgi_application
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
    
    application = get_asgi_application()
    


  6. Why Does Django Need asgi.py?



  7. WSGI vs ASGI — Key Differences

  8. Feature WSGI ASGI
    Type Synchronous Asynchronous + synchronous
    Supports WebSockets? No Yes
    Best Use Case Traditional web apps Real-time & concurrent apps
    Typical Server Gunicorn, uWSGI Uvicorn, Daphne, Hypercorn


  9. Example: Running Django With an ASGI Server

  10. python3 -m venv .venv
    source .venv/bin/activate
    
    python3 -m pip install uvicorn
    
    uvicorn mysite.asgi:application --reload
    


  11. Async Views in Django (ASGI Feature)

  12. # blog/views.py
    
    import asyncio
    from django.http import HttpResponse
    
    async def slow_view(request):
        await asyncio.sleep(2)
        return HttpResponse("This view waited 2 seconds asynchronously!")
    


  13. Using ASGI for WebSockets (Via Django Channels)

  14. python3 -m pip install channels
    
    # mysite/routing.py
    
    from django.urls import path
    from channels.routing import ProtocolTypeRouter, URLRouter
    from blog.consumers import ChatConsumer
    
    application = ProtocolTypeRouter({
        "websocket": URLRouter([
            path("ws/chat/", ChatConsumer.as_asgi()),
        ]),
    })
    


  15. How ASGI Handles a Request (High Level)



  16. Do You Ever Edit asgi.py?




Understanding Django Project & App File Structure

  1. Create a Django Project (Inside Virtual Environment)
  2. python3 -m venv .venv
    source .venv/bin/activate
    
    python3 -m pip install django
    python3 -m django startproject mysite
    cd mysite
    


  3. Django Project Directory Structure

  4. mysite/
    ├── manage.py
    └── mysite/
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        ├── asgi.py
        └── wsgi.py
    


    File / Folder Description
    manage.py Main CLI tool for the project (e.g., runserver, migrate).
    mysite/ (inner folder) Actual project package (contains settings, URLs, ASGI/WSGI).
    __init__.py Makes the folder a Python package.
    settings.py Global configuration: database, installed apps, middleware, templates, static files, etc.
    urls.py Root URL routing file directing to app URLs.
    asgi.py Entry point for ASGI servers (async support).
    wsgi.py Entry point for WSGI servers (production).


  5. Creating an App Inside the Project
  6. python3 manage.py startapp blog
    


  7. Django App Directory Structure
  8. blog/
    ├── admin.py
    ├── apps.py
    ├── models.py
    ├── tests.py
    ├── views.py
    └── migrations/
        └── __init__.py
    

    File / Folder Description
    admin.py Define how models appear in Django Admin.
    apps.py Configuration class for your app (used internally by Django).
    models.py Define your database tables using Django Models.
    tests.py Unit tests for your app.
    views.py Your request handlers (functions or class-based views).
    migrations/ Stores migration files for database schema changes.


  9. Where Do Templates and Static Files Go?


  10. Recommended Structure for Templates
  11. blog/
    ├── templates/
    │   └── blog/
    │       └── index.html
    


  12. Recommended Structure for Static Files
  13. blog/
    ├── static/
    │   └── blog/
    │       ├── style.css
    │       └── script.js
    


  14. How Project and App Work Together

  15. # mysite/settings.py
    
    INSTALLED_APPS = [
        ...
        "blog",
    ]
    
    # mysite/urls.py
    
    from django.urls import path, include
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("blog/", include("blog.urls")),
    ]
    


  16. Example of a Complete App Folder (Realistic)
  17. blog/
    ├── admin.py
    ├── apps.py
    ├── migrations/
    │   ├── __init__.py
    │   └── 0001_initial.py
    ├── models.py
    ├── templates/
    │   └── blog/
    │       └── index.html
    ├── static/
    │   └── blog/
    │       ├── style.css
    │       └── script.js
    ├── tests.py
    └── views.py
    


  18. Example of a Complete Project Folder
  19. mysite/
    ├── manage.py
    ├── mysite/
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   ├── wsgi.py
    │   └── asgi.py
    └── blog/
        ├── admin.py
        ├── apps.py
        ├── migrations/
        ├── models.py
        ├── templates/
        ├── static/
        ├── tests.py
        └── views.py
    



Models in Django

  1. What Are Models?



  2. Typical Workflow With Models

  3. python3 -m venv .venv
    source .venv/bin/activate
    

    python3 -m pip install django
    

    python3 -m django startproject mysite
    cd mysite
    python3 -m django startapp blog
    

    python3 manage.py makemigrations
    python3 manage.py migrate
    


  4. Defining Your First Model

  5. # blog/models.py
    
    from django.db import models
    
    class Post(models.Model):
        title = models.CharField(max_length=200)
        body = models.TextField()
        created_at = models.DateTimeField(auto_now_add=True)
    


  6. Applying Migrations

  7. python3 manage.py makemigrations
    

    python3 manage.py migrate
    


  8. Common Django Model Fields

  9. Field Type Description Example
    CharField Short strings CharField(max_length=100)
    TextField Large text TextField()
    IntegerField Integers IntegerField()
    DateTimeField Date and time values DateTimeField(auto_now_add=True)
    BooleanField True/False BooleanField(default=False)
    ForeignKey Many-to-one relationship ForeignKey(User, on_delete=models.CASCADE)
    FileField File uploads FileField(upload_to="uploads/")


  10. Adding Relationships Between Models

  11. # blog/models.py
    
    from django.db import models
    from django.contrib.auth.models import User
    
    class Comment(models.Model):
        post = models.ForeignKey("Post", on_delete=models.CASCADE)
        author = models.ForeignKey(User, on_delete=models.CASCADE)
        text = models.TextField()
        created_at = models.DateTimeField(auto_now_add=True)
    


  12. Useful Model Methods

  13. class Post(models.Model):
        title = models.CharField(max_length=200)
        body = models.TextField()
    
        def __str__(self):
            return self.title
    
        def preview(self):
            return self.body[:50] + "..."
    


  14. Querying Models Using the ORM

  15. python3 manage.py shell
    
    from blog.models import Post
    
    # Create
    Post.objects.create(title="Hello", body="First post!")
    
    # Read
    Post.objects.all()
    
    # Filter
    Post.objects.filter(title__icontains="hello")
    
    # Order
    Post.objects.order_by("-created_at")
    


  16. Meta Options (Model Configuration)

  17. class Post(models.Model):
        title = models.CharField(max_length=200)
    
        class Meta:
            ordering = ["-id"]
            verbose_name = "Blog Post"
            verbose_name_plural = "Blog Posts"
    


  18. Registering Models in the Admin

  19. # blog/admin.py
    
    from django.contrib import admin
    from .models import Post, Comment
    
    admin.site.register(Post)
    admin.site.register(Comment)
    



Object–Relational Mapper (ORM) in Django

  1. What Is the Django ORM?



  2. Prerequisite: Virtual Environment & Project Setup

  3. python3 -m venv .venv
    source .venv/bin/activate
    python3 -m pip install django
    
    python3 -m django startproject mysite
    cd mysite
    python3 -m django startapp blog
    


  4. Models and Tables

  5. # blog/models.py
    
    from django.db import models
    
    class Post(models.Model):
        title      = models.CharField(max_length=200)
        body       = models.TextField()
        created_at = models.DateTimeField(auto_now_add=True)
    


  6. Migrations: Create the Database Schema

  7. python3 manage.py makemigrations
    
    python3 manage.py migrate
    


  8. Creating Objects (INSERT)

  9. from blog.models import Post
    
    Post.objects.create(title="Hello", body="First post")
    
    INSERT INTO blog_post (title, body, created_at) VALUES (...);
    


  10. Querying Objects (SELECT)

  11. Post.objects.all()
    
    Post.objects.filter(title__icontains="hello")
    
    Post.objects.get(id=1)
    


  12. Common ORM Lookups

  13. Lookup Example Description
    exact title__exact="Hello" Exact match
    icontains title__icontains="hello" Case-insensitive substring match
    gt id__gt=3 Greater than
    lt id__lt=10 Less than
    in id__in=[1, 2, 3] Filter within a list
    startswith title__startswith="Django" Prefix match


  14. Updating Objects (UPDATE)

  15. post = Post.objects.get(id=1)
    post.title = "Updated title"
    post.save()
    


  16. Deleting Objects (DELETE)

  17. post = Post.objects.get(id=1)
    post.delete()
    
    Post.objects.filter(title__icontains="old").delete()
    


  18. ORM and Relationships

  19. class Comment(models.Model):
        post = models.ForeignKey(Post, on_delete=models.CASCADE)
        text = models.TextField()
    
    post = Post.objects.get(id=1)
    comments = post.comment_set.all()
    


  20. Advanced ORM Features

  21. from django.db.models import Count
    
    Post.objects.annotate(comment_count=Count("comment"))
    


  22. Using Django Shell for ORM Testing

  23. python3 manage.py shell
    
    from blog.models import Post
    
    Post.objects.all()
    Post.objects.create(title="New", body="Hello ORM!")
    



Django ORM — Querying Models

  1. Context & Basic Setup

  2. python3 -m venv .venv
    source .venv/bin/activate  # on macOS/Linux
    # .venv\Scripts\activate   # on Windows (PowerShell/cmd)
    python3 manage.py shell


  3. Example model used in this chapter (simplified):
  4. from django.db import models
    
    
    class Author(models.Model):
        name = models.CharField(max_length=100)
    
    
    class Book(models.Model):
        title = models.CharField(max_length=200)
        rating = models.IntegerField(default=0)
        published_at = models.DateField(null=True, blank=True)
        author = models.ForeignKey(
            Author,
            on_delete=models.CASCADE,
            related_name="books",
        )
    
        def __str__(self):
            return f"{self.title} ({self.rating})"
    
    from books.models import Book, Author


  5. Managers & QuerySets



  6. Basic Retrieval: all(), get(), first(), last()



  7. Filtering: filter(), exclude(), field lookups



  8. Combining Conditions: Q Objects (OR / complex logic)



  9. Sorting & Limiting Results: order_by(), slicing



  10. Only Certain Fields: values(), values_list(), only(), defer()



  11. Relations: ForeignKey & Reverse Relations



  12. Performance Helpers: select_related() & prefetch_related()



  13. Aggregations & Annotations: aggregate(), annotate(), F



  14. Creating, Updating, Deleting: create(), update(), delete()



  15. Special Helpers: get_or_create(), update_or_create()



  16. QuerySet Utility Methods: count(), exists(), distinct(), reverse()



  17. Custom Managers & Custom QuerySet Methods




Django Model Filter Pattern

  1. What Is the Django Model Filter Pattern?



  2. Basic Lookup Expressions



  3. Numeric and Comparison Lookups



  4. Date and Time Lookups



  5. Null and Boolean Lookups



  6. Membership Lookups (IN, NOT IN)



  7. Relational Lookups (Foreign Keys)



  8. Reverse Relationship Lookups



  9. Advanced Lookups (Regex, F, Q)



  10. Chaining Filters



  11. Custom Lookups (Extending the Pattern)



  12. Filter vs Exclude vs Get



Models Aggregation in Django (SUM, AVG, COUNT, MAX, MIN, etc.)

  1. What Is Aggregation?



  2. Example Model for This Chapter
  3. # shop/models.py
    
    from django.db import models
    
    class Product(models.Model):
        name = models.CharField(max_length=200)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        stock = models.IntegerField()
        rating = models.FloatField()
    
    python3 manage.py makemigrations
    python3 manage.py migrate
    


  4. Using aggregate()

  5. from django.db.models import Count, Sum, Avg, Max, Min
    
    Product.objects.aggregate(total_count=Count("id"))
    
    {'total_count': 42}
    


  6. COUNT Aggregation
  7. from django.db.models import Count
    
    Product.objects.aggregate(total_products=Count("id"))
    


  8. SUM Aggregation
  9. Product.objects.aggregate(total_stock=Sum("stock"))
    


  10. AVG Aggregation
  11. Product.objects.aggregate(average_price=Avg("price"))
    


  12. MAX and MIN Aggregation
  13. Product.objects.aggregate(
        highest_price=Max("price"),
        lowest_price=Min("price")
    )
    


  14. Multiple Aggregations at Once
  15. Product.objects.aggregate(
        avg_price=Avg("price"),
        total_stock=Sum("stock"),
        max_rating=Max("rating")
    )
    


  16. Using Expressions (F and ExpressionWrapper)
  17. from django.db.models import F, Sum
    
    Product.objects.aggregate(
        total_value=Sum(F("price") * F("stock"))
    )
    


  18. Aggregating With Filters (Filter then Aggregate)
  19. Product.objects
        .filter(rating__gte=4.5)
        .aggregate(high_rated_count=Count("id"))
    


  20. Aggregation With Annotation (Per-row Aggregation)



  21. Example: Total orders per product
  22. from django.db.models import Sum
    
    Product.objects.annotate(
        order_quantity=Sum("order__quantity")
    )
    


  23. Grouping Data (Using values() + annotate())

  24. Product.objects.values("category").annotate(
        avg_price=Avg("price"),
        count=Count("id")
    )
    


  25. Distinct Aggregation

  26. Product.objects.aggregate(
        unique_ratings=Count("rating", distinct=True)
    )
    


  27. Using Aggregation With Related Models
  28. # ForeignKey: Product → Category
    
    Category.objects.annotate(
        total_products=Count("product")
    )
    


  29. Ordering Aggregated Results
  30. Category.objects.annotate(
        total_products=Count("product")
    ).order_by("-total_products")
    


  31. Handling Null Values in Aggregation
  32. Product.objects.aggregate(
        avg_rating=Avg("rating")
    )
    


  33. Raw SQL Equivalent

  34. SELECT AVG(price) AS avg_price FROM shop_product;
    



Models Research — Basic Searching in Django

  1. What Does It Mean?



  2. Example Model for Demonstration
  3. from django.db import models
    
    class Post(models.Model):
        title = models.CharField(max_length=200)
        body = models.TextField()
        created_at = models.DateTimeField(auto_now_add=True)
    
        def __str__(self):
            return self.title
    


  4. Basic Searching With filter()

  5. Post.objects.filter(title="Hello World")
    


  6. Useful Field Lookups for Searching


  7. Lookup Example Description
    icontains title__icontains="django" Case-insensitive substring search (very commonly used)
    contains title__contains="Django" Case-sensitive substring search
    startswith title__startswith="Hello" Search by prefix
    iexact title__iexact="hello" Case-insensitive exact match


  8. Using Q Objects for OR Conditions

  9. from django.db.models import Q
    
    Post.objects.filter(
        Q(title__icontains="django") | Q(body__icontains="django")
    )
    


  10. Searching Across Multiple Fields

  11. query = "hello"
    
    Post.objects.filter(
        Q(title__icontains=query) |
        Q(body__icontains=query)
    )
    


  12. Handling Search Input From a Form
  13. <form method="get">
        <input type="text" name="q" placeholder="Search..." />
        <button type="submit">Go</button>
    </form>
    
    query = request.GET.get("q", "")
    
    results = Post.objects.filter(
        Q(title__icontains=query) |
        Q(body__icontains=query)
    )
    


  14. Is SQL Injection Possible?

  15. Post.objects.filter(title__icontains=request.GET.get("q"))
    


  16. Displaying Simple Search Results
  17. <h2>Results for "{{ q }}"</h2>
    
    {% for post in results %}
        <div>
            <h3>{{ post.title }}</h3>
            <p>{{ post.body|truncatechars:150 }}</p>
        </div>
    {% empty %}
        <p>No matching posts found.</p>
    {% endfor %}
    



Model Managers in Django

  1. What Is a Model Manager?



  2. Default Manager: objects

  3. class Post(models.Model):
        title = models.CharField(max_length=200)
        body = models.TextField()
    
    # Default manager
    Post.objects.all()
    


  4. Creating a Custom Manager
  5. from django.db import models
    
    class PublishedManager(models.Manager):
        def get_queryset(self):
            return super().get_queryset().filter(is_published=True)
    


    class Post(models.Model):
        title = models.CharField(max_length=200)
        body = models.TextField()
        is_published = models.BooleanField(default=False)
    
        objects = models.Manager()           # default manager
        published = PublishedManager()       # custom manager
    

    Post.objects.all()        # returns all posts
    Post.published.all()      # returns only published posts
    


  6. Adding Helper Methods to a Manager

  7. class PostManager(models.Manager):
        def recent(self):
            return self.get_queryset().order_by("-created_at")[:5]
    
    class Post(models.Model):
        ...
        objects = PostManager()
    
    Post.objects.recent()


  8. Multiple Managers on One Model
  9. class Post(models.Model):
        ...
        objects = models.Manager()           # default
        published = PublishedManager()       # custom
        recent = PostManager()               # custom
    
    Post.published.all()
    Post.recent.recent()


  10. Using Managers With ForeignKeys (related_name)
  11. class Comment(models.Model):
        post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="comments")
        text = models.TextField()
    
    post = Post.objects.get(id=1)
    post.comments.all()               # reverse manager
    


  12. The Modern Way: Custom QuerySet + Manager



  13. Replacing the Default Manager

  14. class ActiveManager(models.Manager):
        def get_queryset(self):
            return super().get_queryset().filter(is_deleted=False)
    
    class User(models.Model):
        ...
        objects = ActiveManager()  # replaces default manager
    



Performing Raw SQL Queries in Django Models

  1. Why Use Raw SQL in Django?



  2. Using .raw() for SELECT Queries

  3. # blog/models.py
    from django.db import models
    
    class Post(models.Model):
        title = models.CharField(max_length=200)
        body = models.TextField()
    
    posts = Post.objects.raw("SELECT * FROM blog_post")
    
    for p in posts:
        print(p.title)
    


  4. Using Parameters (Avoid SQL Injection!)

  5. title = "Hello"
    posts = Post.objects.raw(
        "SELECT * FROM blog_post WHERE title = %s",
        [title]
    )
    


  6. Executing Non-SELECT Queries with connection.cursor()

  7. from django.db import connection
    

  8. Example: Manual INSERT
  9. from django.db import connection
    
    def insert_post(title, body):
        with connection.cursor() as cursor:
            cursor.execute(
                "INSERT INTO blog_post (title, body) VALUES (%s, %s)",
                [title, body]
            )
    

  10. Example: Manual UPDATE
  11. with connection.cursor() as cursor:
        cursor.execute(
            "UPDATE blog_post SET title = %s WHERE id = %s",
            ["New Title", 1]
        )
    

  12. Example: Manual DELETE
  13. with connection.cursor() as cursor:
        cursor.execute("DELETE FROM blog_post WHERE id = %s", [1])
    


  14. Fetching Results Manually

  15. with connection.cursor() as cursor:
        cursor.execute("SELECT id, title FROM blog_post")
        rows = cursor.fetchall()
    
    for row in rows:
        print(row)   # (id, title)
    


  16. Using dictfetchall() for Dictionary Results

  17. def dictfetchall(cursor):
        columns = [col[0] for col in cursor.description]
        return [
            dict(zip(columns, row))
            for row in cursor.fetchall()
        ]
    
    with connection.cursor() as cursor:
        cursor.execute("SELECT id, title FROM blog_post")
        results = dictfetchall(cursor)
    
    for item in results:
        print(item["id"], item["title"])
    


  18. Raw Query With Model Mapping + Extra Fields

  19. posts = Post.objects.raw(
        "SELECT id, title, body, NOW() as retrieved_at FROM blog_post"
    )
    
    for p in posts:
        print(p.title)              # model field
        print(p.retrieved_at)       # extra attribute
    


  20. Running Raw SQL on a Specific Database (Multiple DBs)

  21. from django.db import connections
    
    with connections["analytics"].cursor() as cursor:
        cursor.execute("SELECT COUNT(*) FROM stats_table")
        result = cursor.fetchone()
    


  22. Using Model.objects.raw() With Complex Joins

  23. posts = Post.objects.raw("""
        SELECT p.*, COUNT(c.id) AS comment_count
        FROM blog_post p
        LEFT JOIN blog_comment c ON p.id = c.post_id
        GROUP BY p.id
    """)
    



  24. Warnings When Using Raw SQL




  25. Summary




Database Transactions in Django Models

  1. What Are Database Transactions?



  2. Django’s Transaction API Overview

  3. from django.db import transaction
    


  4. Using transaction.atomic (The Most Important Tool)

  5. from django.db import transaction
    
    def create_order(user, product, qty):
        with transaction.atomic():
            order = Order.objects.create(user=user)
            OrderItem.objects.create(order=order, product=product, quantity=qty)
            product.stock -= qty
            product.save()
    


  6. Using atomic as a Decorator
  7. @transaction.atomic
    def add_post(title, body):
        Post.objects.create(title=title, body=body)
    


  8. Nested atomic() Blocks

  9. with transaction.atomic():
        # outer transaction
        Post.objects.create(title="Main")
    
        try:
            with transaction.atomic():
                # inner savepoint
                Comment.objects.create(text="Inner comment")
                raise ValueError("fail inner")   # only inner part rolls back
        except:
            pass
    
        Post.objects.create(title="Still saved")
    


  10. Manually Controlling Savepoints
  11. sid = transaction.savepoint()
    try:
        Product.objects.create(name="ABC")
        transaction.savepoint_commit(sid)
    except:
        transaction.savepoint_rollback(sid)
    


  12. Using transaction.on_commit()

  13. from django.db import transaction
    
    @transaction.atomic
    def register_user(user):
        user.save()
        transaction.on_commit(lambda: print("User created:", user.id))
    


  14. Autocommit Mode (Default)

  15. from django.db import transaction
    
    transaction.get_autocommit()   # True
    


  16. Disabling Autocommit (Advanced)

  17. transaction.set_autocommit(False)
    
    try:
        Product.objects.create(name="X")
        transaction.commit()
    except:
        transaction.rollback()
    


  18. Marking a Transaction for Rollback

  19. with transaction.atomic():
        transaction.set_rollback(True)
    


  20. Transactions in Views
  21. from django.db import transaction
    from django.http import HttpResponse
    
    @transaction.atomic
    def my_view(request):
        Order.objects.create(...)
        return HttpResponse("Order placed!")
    


  22. Handling Integrity Errors

  23. from django.db import IntegrityError, transaction
    
    try:
        with transaction.atomic():
            User.objects.create(username="same")
    except IntegrityError:
        print("Duplicate username!")
    



Using Multiple Databases in Django Models

  1. Why Use Multiple Databases?



  2. Defining Multiple Databases in settings.py

  3. # mysite/settings.py
    
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.sqlite3",
            "NAME": BASE_DIR / "db.sqlite3",
        },
        "analytics": {
            "ENGINE": "django.db.backends.sqlite3",
            "NAME": BASE_DIR / "analytics.sqlite3",
        },
    }
    


  4. Running Migrations on a Specific Database
  5. python3 manage.py migrate --database=analytics
    


  6. Saving an Object to a Specific Database

  7. post = Post(title="Hello", body="World")
    post.save(using="analytics")
    


  8. Querying a Specific Database
  9. Post.objects.using("analytics").all()
    


  10. Deleting From a Specific Database
  11. post.delete(using="analytics")
    


  12. Using Multiple Databases with Raw SQL
  13. from django.db import connections
    
    with connections["analytics"].cursor() as cursor:
        cursor.execute("SELECT COUNT(*) FROM blog_post")
        count = cursor.fetchone()
    


  14. Database Routers (Core of Multi-DB Architecture)

  15. # mysite/dbrouters.py
    
    class AnalyticsRouter:
        app_label = "analytics_app"
    
        def db_for_read(self, model, **hints):
            if model._meta.app_label == self.app_label:
                return "analytics"
            return None
    
        def db_for_write(self, model, **hints):
            if model._meta.app_label == self.app_label:
                return "analytics"
            return None
    
        def allow_migrate(self, db, app_label, model_name=None, **hints):
            if app_label == self.app_label:
                return db == "analytics"
            return None
    


  16. Activating Database Routers
  17. # mysite/settings.py
    
    DATABASE_ROUTERS = ["mysite.dbrouters.AnalyticsRouter"]
    


  18. Models and App Label for Routing

  19. class Report(models.Model):
        ...
    
        class Meta:
            app_label = "analytics_app"
    


  20. Reading from One DB and Writing to Another

  21. replicas = ["replica1", "replica2"]
    
    def random_read_db():
        import random
        return random.choice(replicas)
    
    Post.objects.using(random_read_db()).filter(...)
    


  22. Transaction Management With Multiple Databases

  23. from django.db import transaction
    
    with transaction.atomic(using="default"):
        # write to default DB
        ...
    
    with transaction.atomic(using="analytics"):
        # write to analytics DB
        ...
    


  24. Cross-Database Foreign Keys Are Not Allowed

  25. def allow_relation(self, obj1, obj2, **hints):
        if obj1._state.db == obj2._state.db:
            return True
        return False
    


  26. Using Different Databases for Different Django Apps

  27. class ShopRouter:
        def db_for_read(self, model, **hints):
            if model._meta.app_label == "analytics_app":
                return "analytics"
            return "default"
    



Understanding the DATABASES Setting in Django

  1. What Is the DATABASES Setting?


  2. The Basic Structure of DATABASES

  3. # settings.py
    
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.sqlite3",
            "NAME": BASE_DIR / "db.sqlite3",
        }
    }
    


  4. Supported Database Engines


  5. ENGINE Description Example
    django.db.backends.sqlite3 Default, file-based database (good for development). "NAME": BASE_DIR / "db.sqlite3"
    django.db.backends.postgresql PostgreSQL (recommended for production). "ENGINE": "django.db.backends.postgresql"
    django.db.backends.mysql MySQL or MariaDB. "ENGINE": "django.db.backends.mysql"
    django.db.backends.oracle Oracle database. "ENGINE": "django.db.backends.oracle"


  6. Full Configuration Example (PostgreSQL)
  7. DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.postgresql",
            "NAME": "mydatabase",
            "USER": "myuser",
            "PASSWORD": "mypassword",
            "HOST": "localhost",
            "PORT": "5432",
        }
    }
    


  8. Explanation of All Common Options

  9. Option Description Example
    ENGINE Database backend to use. "django.db.backends.postgresql"
    NAME Database name (or file path for SQLite). "mydb"
    USER Database username. "dbuser"
    PASSWORD Password for the database user. "secret"
    HOST Database host (IP or domain). "127.0.0.1"
    PORT Database port number. "5432"
    OPTIONS Advanced backend-specific options. {"sslmode": "require"}
    ATOMIC_REQUESTS If True: each HTTP request is wrapped in a DB transaction. True
    AUTOCOMMIT True = auto commit transactions (recommended). True
    CONN_MAX_AGE Persistent DB connections (seconds or None). 60
    TEST Overrides DB settings for testing. {"NAME": "testdb"}


  10. SQLite Special Case

  11. DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.sqlite3",
            "NAME": BASE_DIR / "db.sqlite3",
        }
    }
    


  12. Using Environment Variables (Best Practice!)

  13. import os
    
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.postgresql",
            "NAME": os.environ["DB_NAME"],
            "USER": os.environ["DB_USER"],
            "PASSWORD": os.environ["DB_PASSWORD"],
            "HOST": os.environ["DB_HOST"],
            "PORT": os.environ["DB_PORT"],
        }
    }
    


  14. Multiple Databases

  15. DATABASES = {
        "default": {...},
        "analytics": {...},
        "legacy": {...},
    }
    


  16. Database Transactions and ATOMIC_REQUESTS

  17. DATABASES = {
        "default": {
            ...
            "ATOMIC_REQUESTS": True,
        }
    }
    


  18. Persistent Connections (CONN_MAX_AGE)

  19. CONN_MAX_AGE = 60       # keep connection for one minute
    # CONN_MAX_AGE = None   # keep forever
    


  20. Testing Database Settings

  21. DATABASES = {
        "default": {
            ...
            "TEST": {
                "NAME": "test_mysite"
            }
        }
    }
    



Understanding models.Model in Django

  1. What Is models.Model?




  2. How models.Model Creates a Database Table

  3. python3 manage.py makemigrations
    python3 -m django migrate
    
    CREATE TABLE app_post (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        title VARCHAR(200) NOT NULL,
        body TEXT NOT NULL
    );
    


  4. Automatic Primary Key Field (id)

  5. id = models.AutoField(primary_key=True)
    
    class User(models.Model):
        user_id = models.UUIDField(primary_key=True)
        username = models.CharField(max_length=50)
    


  6. Defining Fields (Columns)

  7. class Product(models.Model):
        name = models.CharField(max_length=100)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        available = models.BooleanField(default=True)
        created_at = models.DateTimeField(auto_now_add=True)
    


  8. Model Instances = Rows

  9. p = Product(name="Laptop", price=999.99)
    p.save()       # INSERT into database
    
    p.price = 899.99
    p.save()       # UPDATE in database
    


  10. Deleting Rows
  11. p = Product.objects.get(id=1)
    p.delete()   # DELETE FROM table
    


  12. Meta Class: Controlling Table Options

  13. class Product(models.Model):
        name = models.CharField(max_length=100)
        price = models.DecimalField(max_digits=8, decimal_places=2)
    
        class Meta:
            db_table = "store_products"
            ordering = ["name"]
            verbose_name = "Product"
            verbose_name_plural = "Products"
            indexes = [
                models.Index(fields=["name"]),
            ]
    


  14. Model Methods: Custom Business Logic

  15. class Product(models.Model):
        price = models.DecimalField(max_digits=8, decimal_places=2)
    
        def discounted_price(self, percent):
            return self.price * (1 - percent / 100)
    


  16. String Representation (__str__)

  17. class Product(models.Model):
        name = models.CharField(max_length=100)
    
        def __str__(self):
            return f"Product({self.name})"
    


  18. Custom Save Logic (Overriding save())
  19. class Order(models.Model):
        total = models.DecimalField(max_digits=10, decimal_places=2)
    
        def save(self, *args, **kwargs):
            print("Before saving...")
            super().save(*args, **kwargs)
            print("After saving...")
    


  20. Custom Delete Logic (Overriding delete())
  21. def delete(self, *args, **kwargs):
        print("Deleting:", self)
        super().delete(*args, **kwargs)
    


  22. Foreign Keys and Relations

  23. class Category(models.Model):
        name = models.CharField(max_length=50)
    
    class Product(models.Model):
        category = models.ForeignKey(Category, on_delete=models.CASCADE)
    
    cat = Category.objects.get(id=1)
    cat.product_set.all()      # All products in the category
    


  24. Model Managers

  25. products = Product.objects.filter(price__lt=50)
    


  26. Full Lifecycle of a Model Row

  27. obj = Product.objects.create(name="Pen", price=2)
    
    obj = Product.objects.get(id=1)
    
    obj.price = 3
    obj.save()
    
    obj.delete()
    



Understanding the class Meta Options in Django Models

  1. What Is the Meta Class?



  2. Basic Structure of Meta
  3. class Product(models.Model):
        name = models.CharField(max_length=50)
    
        class Meta:
            ordering = ["name"]
    


  4. Full List of Common Meta Options

  5. Option Purpose
    db_tableCustom SQL table name
    orderingDefault ordering for QuerySets
    verbose_nameHuman-readable singular name
    verbose_name_pluralPlural human-readable name
    indexesCustom database indexes
    unique_togetherMulti-field uniqueness constraint (legacy)
    constraintsAdvanced database constraints
    permissionsCustom permission definitions
    default_related_nameReverse relationship name
    app_labelAssign model to a different app
    managedIf False, Django will NOT create or modify the table
    get_latest_byField used by QuerySet.latest()
    orderingSet default ordering (ASC/DESC)
    abstractCreate abstract base classes
    proxyCreate proxy models


  6. db_table — Custom Table Name

  7. class Product(models.Model):
        name = models.CharField(max_length=50)
    
        class Meta:
            db_table = "ecommerce_products"
    


  8. ordering — Default QuerySet Order

  9. class Post(models.Model):
        created_at = models.DateTimeField()
    
        class Meta:
            ordering = ["-created_at"]
    


  10. verbose_name & verbose_name_plural

  11. class Product(models.Model):
        class Meta:
            verbose_name = "Product Item"
            verbose_name_plural = "Product Items"
    


  12. indexes — Creating Database Indexes
  13. class User(models.Model):
        username = models.CharField(max_length=50)
        email = models.EmailField()
    
        class Meta:
            indexes = [
                models.Index(fields=["username"]),
                models.Index(fields=["email"]),
            ]
    


  14. unique_together (Deprecated in Favor of UniqueConstraint)
  15. class Enrollment(models.Model):
        student = models.ForeignKey("Student", on_delete=models.CASCADE)
        course = models.ForeignKey("Course", on_delete=models.CASCADE)
    
        class Meta:
            unique_together = ["student", "course"]
    


  16. constraints — Advanced SQL Constraints
  17. from django.db import models
    
    class Product(models.Model):
        price = models.DecimalField(max_digits=10, decimal_places=2)
    
        class Meta:
            constraints = [
                models.CheckConstraint(check=models.Q(price__gte=0), name="price_positive")
            ]
    


  18. permissions — Custom Permissions
  19. class Report(models.Model):
        class Meta:
            permissions = [
                ("view_sensitive_data", "Can view sensitive data"),
                ("export_reports", "Can export reports"),
            ]
    


  20. default_related_name — Reverse Relation Name
  21. class Author(models.Model):
        class Meta:
            default_related_name = "authors"
    


  22. managed — Should Django Create This Table?
  23. class LegacyUser(models.Model):
        legacy_id = models.IntegerField()
    
        class Meta:
            managed = False
            db_table = "legacy_user_table"
    


  24. get_latest_by — Field Used by latest()
  25. class Event(models.Model):
        timestamp = models.DateTimeField()
    
        class Meta:
            get_latest_by = "timestamp"
    


  26. abstract — Create an Abstract Base Class
  27. class BaseTimestamp(models.Model):
        created = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            abstract = True
    


  28. proxy — Create a Proxy Model
  29. class OrderedUser(User):
        class Meta:
            proxy = True
            ordering = ["username"]
    


  30. app_label — Force a Model into a Different App

  31. class Report(models.Model):
        class Meta:
            app_label = "analytics"
    



Understanding Tablespaces in Django Models

  1. What Are Tablespaces?



  2. Basic Syntax for Using Tablespaces

  3. class Report(models.Model):
        name = models.CharField(max_length=100)
    
        class Meta:
            db_tablespace = "report_tablespace"
            default_related_name = "reports"
    


  4. How to Set Tablespaces for Indexes

  5. class Report(models.Model):
        title = models.CharField(max_length=200)
    
        class Meta:
            db_tablespace = "ts_reports"
            indexes = [
                models.Index(fields=["title"], db_tablespace="ts_indexes"),
            ]
    


  6. Setting Tablespaces for All Models in an App

  7. DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.postgresql",
            "NAME": "mydb",
            "USER": "myuser",
        }
    }
    
    DEFAULT_TABLESPACE = "mysite_default_ts"
    DEFAULT_INDEX_TABLESPACE = "mysite_index_ts"
    


  8. Full Example: Table + Index Tablespaces
  9. class Document(models.Model):
        title = models.CharField(max_length=255)
        uploaded_at = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            db_tablespace = "docs_ts"
            indexes = [
                models.Index(
                    fields=["uploaded_at"],
                    name="upload_time_idx",
                    db_tablespace="docs_idx_ts",
                ),
            ]
    


  10. Checking Tablespaces in Generated SQL

  11. python3 manage.py sqlmigrate appname 0001
    
    CREATE TABLE "app_document" (
        "id" serial NOT NULL PRIMARY KEY,
        "title" varchar(255) NOT NULL,
        "uploaded_at" timestamp with time zone NOT NULL
    ) TABLESPACE docs_ts;
    
    CREATE INDEX upload_time_idx
        ON "app_document" ("uploaded_at")
        TABLESPACE docs_idx_ts;
    


  12. What Happens if Your Database Doesn’t Support Tablespaces?




Database Access Optimization in Django

  1. Why Database Optimization Matters



  2. Django Debug Toolbar (Essential Tool)



  3. Use select_related() for ForeignKey and OneToOne


  4. books = Book.objects.select_related("author")
    for book in books:
        print(book.author.name)
    


  5. Use prefetch_related() for Many-to-Many and Reverse Relations

  6. authors = Author.objects.prefetch_related("books")
    
    for author in authors:
        print(author.books.all())
    


  7. Avoid Loading Unneeded Fields (values() & only())

  8. products = Product.objects.values("id", "name")
    

    users = User.objects.only("id", "username")
    


  9. Avoid .count() on QuerySets Without Filtering

  10. total = Product.objects.count()  # efficient
    
    len(Product.objects.all())   # loads EVERYTHING into memory → slow!
    


  11. Use Indexes for Fast Filtering

  12. class Product(models.Model):
        name = models.CharField(max_length=200)
        class Meta:
            indexes = [
                models.Index(fields=["name"]),
            ]
    


  13. Use exists() Instead of Fetching Objects

  14. if User.objects.filter(email=email).exists():
        ...
    
    SELECT (1) AS a FROM user WHERE email=... LIMIT 1;
    


  15. Avoid Query Inside a Loop

  16. for user in User.objects.all():
        print(Order.objects.filter(user=user).count())
    

    users = User.objects.prefetch_related("order_set")
    


  17. Use bulk_create() for Inserting Many Rows

  18. objs = [Log(msg=f"Item {i}") for i in range(1000)]
    Log.objects.bulk_create(objs, batch_size=200)
    


  19. Use bulk_update() for Batch Updates

  20. products = Product.objects.filter(on_sale=True)
    for p in products:
        p.discount = 10
    
    Product.objects.bulk_update(products, ["discount"])
    


  21. Use iterator() for Large QuerySets

  22. for row in BigTable.objects.iterator():
        process(row)
    


  23. Cache Aggressive Queries
  24. from django.core.cache import cache
    
    data = cache.get("stats")
    if data is None:
        data = calculate_stats()
        cache.set("stats", data, timeout=3600)
    


  25. Use Raw SQL Only When Needed
  26. from django.db import connection
    
    cursor = connection.cursor()
    cursor.execute("SELECT COUNT(*) FROM app_table")
    



Database Instrumentation in Django

  1. What Is Database Instrumentation?



  2. The Building Block: django.db.connection.queries

  3. from django.db import connection
    
    print(connection.queries)
    
    [
        {
            "sql": "SELECT ...",
            "time": "0.001",
        },
    ]
    


  4. Measuring Query Time in Views

  5. from django.db import connection, reset_queries
    import time
    
    def view(request):
        reset_queries()
        start = time.time()
    
        # Your ORM logic here
        users = User.objects.select_related("profile").all()
    
        total_time = time.time() - start
        print("Queries:", len(connection.queries))
        print("Time:", total_time)
    
        return HttpResponse("OK")
    


  6. Using django-debug-toolbar for Query Profiling



  7. Using Logging to Capture SQL Queries

  8. LOGGING = {
        "version": 1,
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
            },
        },
        "loggers": {
            "django.db.backends": {
                "handlers": ["console"],
                "level": "DEBUG",
            },
        },
    }
    


  9. Using QuerySet.explain() to Analyze SQL Execution Plans

  10. qs = User.objects.filter(email__icontains="gmail.com")
    print(qs.explain())
    


  11. Tracking Connection Usage
  12. from django.db import connection
    
    print("Connection open:", connection.connection is not None)
    print("In transaction:", connection.in_atomic_block)
    
    from django.db import connections
    
    print(connections["default"].queries)
    print(connections["analytics"].queries)
    


  13. Using Database-Level Monitoring Tools


  14. Instrumenting ORM Internals With Signals
  15. from django.db.models.signals import post_save
    from django.dispatch import receiver
    
    @receiver(post_save)
    def log_save(sender, instance, created, **kwargs):
        if created:
            print(f"Created row in table: {sender.__name__}")
        else:
            print(f"Updated row in table: {sender.__name__}")
    


  16. Instrumenting Transactions
  17. from django.db import transaction
    
    with transaction.atomic():
        print("In transaction:", connection.in_atomic_block)
    


  18. Middleware for Query Profiling

  19. from django.db import connection
    
    class QueryCountMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            num_before = len(connection.queries)
            response = self.get_response(request)
            num_after = len(connection.queries)
            print("Queries this request:", num_after - num_before)
            return response
    



Understanding Database Fixtures in Django

  1. What Are Fixtures in Django?



  2. Supported Fixture Formats


  3. Format Extension Notes
    JSON .json Most common, human-readable
    YAML .yaml / .yml Requires PyYAML
    XML .xml Verbose, rarely used today



  4. Where to Store Fixture Files

  5. 
    your_app/
        fixtures/
            mydata.json
    
    FIXTURE_DIRS = [
        BASE_DIR / "project_fixtures",
    ]
    


  6. Fixture File Structure (JSON Example)

  7. [
      {
        "model": "shop.product",
        "pk": 1,
        "fields": {
          "name": "Laptop",
          "price": "1299.99",
          "in_stock": true
        }
      },
      {
        "model": "shop.product",
        "pk": 2,
        "fields": {
          "name": "Mouse",
          "price": "29.99",
          "in_stock": true
        }
      }
    ]
    


  8. Loading Fixtures into the Database

  9. python3 manage.py loaddata mydata.json
    
    python3 manage.py loaddata mydata.json --database=analytics
    


  10. Dumping Existing Database Data to Fixtures
  11. python3 manage.py dumpdata shop.Product > products.json
    
    python3 manage.py dumpdata > all.json
    
    python3 manage.py dumpdata --exclude auth.permission --exclude contenttypes > data.json
    


  12. Dumping Data for Specific App or Model
  13. python3 manage.py dumpdata shop --indent 4
    


  14. Understanding the loaddata Search Path

  15. 
    1. App's fixtures/ directories
    2. Directories listed in FIXTURE_DIRS
    3. Absolute or relative paths given directly
    
    python3 manage.py loaddata /tmp/data/initial.json
    


  16. Common Fixture Use Cases



  17. Using Fixtures in Tests

  18. from django.test import TestCase
    
    class ProductTests(TestCase):
        fixtures = ["products.json"]
    
        def test_count(self):
            self.assertEqual(Product.objects.count(), 10)
    


  19. Relational Data in Fixtures

  20. [
      {
        "model": "shop.order",
        "pk": 1,
        "fields": { "user": 5, "product": 2 }
      }
    ]
    


  21. Handling Natural Keys (Better for Human-Readable Fixtures)

  22. class User(models.Model):
        username = models.CharField(max_length=50, unique=True)
    
        def natural_key(self):
            return (self.username,)
    
    [
      {
        "model": "auth.user",
        "fields": { "username": "alice" }
      }
    ]
    


  23. Best Practices for Fixtures



  24. Summary




URL Dispatcher in Django

  1. What Is the URL Dispatcher?



  2. Request Flow: From Browser to View

  3. Browser  -->  Django (WSGI/ASGI)  -->  ROOT_URLCONF (mysite/urls.py)
                                             |
                                             V
                                      urlpatterns list
                                             |
                                             V
                                   include("blog.urls") for "blog/"
                                             |
                                             V
                                    blog/urls.py: path("hello/", views.hello)
                                             |
                                             V
                                       views.hello(request)
    


  4. Basic URL Patterns with path()

  5. # mysite/urls.py
    
    from django.contrib import admin
    from django.urls import path
    from blog import views
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("hello/", views.hello),   # maps /hello/ to views.hello
    ]
    

    # blog/views.py
    
    from django.http import HttpResponse
    
    def hello(request):
        return HttpResponse("Hello from the URL dispatcher!")
    


  6. Regular Expressions with re_path()

  7. from django.urls import re_path
    from blog import views
    
    urlpatterns = [
        re_path(r"^archive/(?P<year>[0-9]{4})/$", views.year_archive),
    ]
    
    def year_archive(request, year):
        return HttpResponse(f"Archive for year {year}")
    


  8. Splitting Routes by App with include()

  9. # blog/urls.py
    
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path("hello/", views.hello),
        path("about/", views.about),
    ]
    
    # mysite/urls.py
    
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("blog/", include("blog.urls")),   # mounts blog.urls under /blog/
    ]
    


  10. Dynamic Segments with Path Converters

  11. # blog/urls.py
    
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path("post/<int:post_id>/", views.post_detail, name="post-detail"),
    ]
    
    # blog/views.py
    
    def post_detail(request, post_id):
        return HttpResponse(f"Post id is {post_id}")
    


  12. Custom Path Converters (Advanced)

  13. # blog/converters.py
    
    class LowercaseConverter:
        regex = "[a-z]+"
    
        def to_python(self, value):
            return value   # can transform the value if needed
    
        def to_url(self, value):
            return value.lower()
    
    # mysite/urls.py
    
    from django.contrib import admin
    from django.urls import path, include, register_converter
    from blog.converters import LowercaseConverter
    
    register_converter(LowercaseConverter, "lower")
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("blog/", include("blog.urls")),
    ]
    
    # blog/urls.py
    
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path("user/<lower:username>/", views.profile),
    ]
    


  14. Order, Matching Rules, and 404 Errors

  15. urlpatterns = [
        path("post/<int:id>/", views.post_by_id),
        path("post/latest/", views.latest_post),
    ]
    
    urlpatterns = [
        path("post/latest/", views.latest_post),
        path("post/<int:id>/", views.post_by_id),
    ]
    


  16. Named URLs and Reverse Resolution

  17. # blog/urls.py
    
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path("hello/", views.hello, name="hello"),
    ]
    
    from django.urls import reverse
    
    url = reverse("hello")   # returns "/hello/"
    
    <a href="{% url 'hello' %}">Say hello</a>
    


  18. Class-Based Views and as_view()

  19. # blog/views.py
    
    from django.views import View
    from django.http import HttpResponse
    
    class HelloView(View):
        def get(self, request):
            return HttpResponse("Hello from class-based view!")
    
    # blog/urls.py
    
    from django.urls import path
    from .views import HelloView
    
    urlpatterns = [
        path("hello/", HelloView.as_view(), name="hello-class"),
    ]
    


  20. Static Files, Media, and Other Helpers

  21. # mysite/urls.py
    
    from django.contrib import admin
    from django.urls import path, include
    from django.conf import settings
    from django.conf.urls.static import static
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("blog/", include("blog.urls")),
    ]
    
    if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    



Beginner's Guide to Views in Django

  1. What Is a View?



  2. Your First View

  3. from django.http import HttpResponse
    
    def hello(request):
        return HttpResponse("Hello, Django beginner!")
    
    # blog/urls.py
    
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path("hello/", views.hello),
    ]
    


  4. Views Should Return HttpResponse

  5. def hi(request):
        return HttpResponse("Hi from Django!")
    
    def html_example(request):
        return HttpResponse("<h1>Welcome</h1><p>This is HTML.</p>")
    


  6. Views That Use Templates

  7. from django.shortcuts import render
    
    def home(request):
        return render(request, "blog/home.html")
    
    <!-- blog/templates/blog/home.html -->
    <h1>Welcome to my blog</h1>
    <p>This page is rendered using a Django template.</p>
    


  8. Passing Data from View to Template

  9. def home(request):
        data = {"name": "Alice", "hobby": "Reading"}
        return render(request, "blog/home.html", data)
    
    <h1>Hello {{ name }}!</h1>
    <p>Your hobby is {{ hobby }}.</p>
    


  10. Views with URL Parameters

  11. path("post/<int:id>/", views.show_post)
    
    def show_post(request, id):
        return HttpResponse(f"You requested post {id}")
    


  12. Handling GET and POST Requests

  13. def contact(request):
        if request.method == "GET":
            return HttpResponse("This is the contact form page.")
        if request.method == "POST":
            return HttpResponse("Form submitted!")
    


  14. Redirecting from a View

  15. from django.shortcuts import redirect
    
    def go_home(request):
        return redirect("/blog/hello/")
    


  16. Class-Based Views (Very Beginner-Friendly)

  17. from django.views import View
    from django.http import HttpResponse
    
    class HelloView(View):
        def get(self, request):
            return HttpResponse("Hello from a class-based view!")
    
    path("hello-class/", HelloView.as_view())
    


  18. What Should a Beginner Focus On?




Views in Django

  1. What Is a View?



  2. Simple Function-Based View (FBV)

  3. # blog/views.py
    
    from django.http import HttpResponse
    
    def hello(request):
        return HttpResponse("Hello from a Django view!")
    
    # blog/urls.py
    
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path("hello/", views.hello),
    ]
    


  4. Returning HTML with HttpResponse

  5. def home(request):
        return HttpResponse("<h1>Welcome!</h1><p>This is raw HTML.</p>")
    


  6. Rendering Templates

  7. # blog/views.py
    
    from django.shortcuts import render
    
    def home(request):
        return render(request, "blog/home.html")
    
    <!-- blog/templates/blog/home.html -->
    <h1>Blog Home</h1>
    <p>Rendered by Django.</p>
    


  8. Passing Data to Templates

  9. def home(request):
        context = {
            "title": "My Blog",
            "posts": ["Post A", "Post B"],
        }
        return render(request, "blog/home.html", context)
    
    <h1>{{ title }}</h1>
    <ul>
        {% for p in posts %}
            <li>{{ p }}</li>
        {% endfor %}
    </ul>
    


  10. Returning JSON Responses

  11. from django.http import JsonResponse
    
    def api_info(request):
        return JsonResponse({"status": "ok", "version": 1})
    


  12. Handling URL Parameters

  13. # blog/views.py
    
    def show_post(request, post_id):
        return HttpResponse(f"Post ID is {post_id}")
    
    path("post/<int:post_id>/", views.show_post)
    


  14. Class-Based Views (CBV)

  15. from django.views import View
    from django.http import HttpResponse
    
    class HelloView(View):
        def get(self, request):
            return HttpResponse("Hello from a class-based view!")
    
    path("hello/", HelloView.as_view())
    


  16. Advantages of Class-Based Views



  17. Generic Class-Based Views (GCBV)

  18. from django.views.generic import ListView
    from .models import Post
    
    class PostListView(ListView):
        model = Post                             # Tell Django which model you want to list
        template_name = "blog/posts.html"
        context_object_name = "posts"
    

    path("posts/", PostListView.as_view())
    

    <!-- blog/templates/blog/posts.html -->
    <!doctype html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>All Posts</title>
    </head>
    <body>
        <h1>All Posts</h1>
    
        <ul>
        {% for post in posts %}
            <li>
                <h2>{{ post.title }}</h2>
                <p>{{ post.body|truncatechars:100 }}</p>
            </li>
        {% empty %}
            <li>No posts yet.</li>
        {% endfor %}
        </ul>
    </body>
    </html>
    


  19. Redirecting from Views

  20. from django.shortcuts import redirect
    
    def go_home(request):
        return redirect("/hello/")
    


  21. Handling HTTP Methods Manually

  22. def contact(request):
        if request.method == "GET":
            return HttpResponse("Form page")
        elif request.method == "POST":
            return HttpResponse("Processing form...")
    


  23. Using Decorators in Views

  24. from django.contrib.auth.decorators import login_required
    
    @login_required
    def dashboard(request):
        return HttpResponse("Dashboard")
    


  25. Error Views

  26. # in mysite/urls.py
    
    handler404 = "mysite.views.not_found"
    handler500 = "mysite.views.server_error"
    
    def not_found(request, exception):
        return HttpResponse("Page not found", status=404)
    



HttpResponse in Django

  1. What Is HttpResponse?



  2. Basic Usage of HttpResponse

  3. from django.http import HttpResponse
    
    def hello(request):
        return HttpResponse("Hello World!")
    


  4. Returning HTML via HttpResponse

  5. def home(request):
        return HttpResponse("<h1>Welcome</h1><p>This is direct HTML.</p>")
    


  6. Setting Content Types

  7. def plain_text(request):
        return HttpResponse("Just text", content_type="text/plain")
    


  8. Returning Binary Data

  9. def raw_png(request):
        with open("logo.png", "rb") as f:
            data = f.read()
        return HttpResponse(data, content_type="image/png")
    


  10. Setting HTTP Status Codes

  11. def not_found(request):
        return HttpResponse("Not here", status=404)
    


  12. Adding Custom Headers

  13. def custom_headers(request):
        response = HttpResponse("OK")
        response["X-Powered-By"] = "Django"
        return response
    


  14. HttpResponse Subclasses

  15. from django.http import JsonResponse
    
    def api(request):
        return JsonResponse({"result": 123})
    


  16. HttpResponse and Templates

  17. from django.shortcuts import render
    
    def home(request):
        return render(request, "blog/home.html")
    


  18. HttpResponse with Cookies

  19. def set_cookie(request):
        response = HttpResponse("Cookie set")
        response.set_cookie("theme", "dark")
        return response
    


  20. StreamingHttpResponse (Advanced)

  21. from django.http import StreamingHttpResponse
    
    def stream_numbers(request):
        def generator():
            for i in range(1, 6):
                yield f"Number: {i}\n"
        return StreamingHttpResponse(generator())
    


  22. FileResponse (Efficient File Downloads)

  23. from django.http import FileResponse
    
    def download(request):
        return FileResponse(open("report.pdf", "rb"), as_attachment=True)
    



Writing Views in Django

  1. What Does It Mean to “Write a View”?



  2. Start With a Simple View

  3. from django.http import HttpResponse
    
    def hello(request):
        return HttpResponse("Hello! This is my first view.")
    
    # blog/urls.py
    
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path("hello/", views.hello),
    ]
    


  4. Views That Return HTML

  5. def welcome(request):
        return HttpResponse("<h1>Welcome</h1><p>This is a simple HTML page.</p>")
    


  6. Rendering Templates (Recommended)

  7. from django.shortcuts import render
    
    def home(request):
        return render(request, "blog/home.html")
    
    <!-- blog/templates/blog/home.html -->
    <h1>Blog Home</h1>
    <p>This page was rendered using a template!</p>
    


  8. Passing Data to a Template

  9. def about(request):
        info = {
            "title": "About This Blog",
            "author": "Junzhe",
        }
        return render(request, "blog/about.html", info)
    
    <!-- blog/templates/blog/about.html -->
    <h1>{{ title }}</h1>
    <p>Created by {{ author }}.</p>
    


  10. Views With URL Parameters

  11. # blog/urls.py
    path("post/<int:id>/", views.show_post)
    
    def show_post(request, id):
        return HttpResponse(f"You asked for post {id}")
    


  12. Views That Handle GET and POST

  13. def contact(request):
        if request.method == "GET":
            return HttpResponse("This is the contact page.")
        elif request.method == "POST":
            return HttpResponse("You submitted the form!")
    


  14. Redirects in Views

  15. from django.shortcuts import redirect
    
    def go_to_home(request):
        return redirect("/blog/home/")
    


  16. Writing Class-Based Views (Beginner Level)

  17. from django.views import View
    from django.http import HttpResponse
    
    class HelloView(View):
        def get(self, request):
            return HttpResponse("Hello from a class-based view!")
    
    path("hello-class/", HelloView.as_view())
    


  18. Where Should You Write Views?

  19. blog/
    ├── admin.py
    ├── apps.py
    ├── models.py
    ├── views.py   <-- write your views here
    ├── tests.py
    └── migrations/
    


  20. A Good Beginner Workflow for Writing Views




Beginner's Guide to View Decorators in Django

  1. What Is a View Decorator?

  2. @decorator_name
    def my_view(request):
        ...
    


  3. Why Do We Use Decorators?



  4. Decorator #1: login_required

  5. from django.contrib.auth.decorators import login_required
    from django.http import HttpResponse
    
    @login_required
    def dashboard(request):
        return HttpResponse("Welcome to your dashboard!")
    


  6. Decorator #2: require_http_methods

  7. from django.views.decorators.http import require_http_methods
    from django.http import HttpResponse
    
    @require_http_methods(["GET", "POST"])
    def contact(request):
        return HttpResponse("This view accepts only GET and POST")
    


  8. Decorator #3: require_GET and require_POST

  9. from django.views.decorators.http import require_GET
    
    @require_GET
    def homepage(request):
        return HttpResponse("Only GET requests are allowed here!")
    
    from django.views.decorators.http import require_POST
    
    @require_POST
    def save_data(request):
        return HttpResponse("Only POST requests accepted.")
    


  10. Decorator #4: csrf_exempt

  11. from django.views.decorators.csrf import csrf_exempt
    
    @csrf_exempt
    def webhook(request):
        return HttpResponse("CSRF check skipped for this view.")
    


  12. Decorator #5: cache_page

  13. from django.views.decorators.cache import cache_page
    
    @cache_page(60)  # cache for 60 seconds
    def news(request):
        return HttpResponse("This page is cached for 1 minute.")
    


  14. How Decorators Work (beginner explanation)

  15. @my_decorator
    def my_view(request):
        ...
    
    my_view = my_decorator(my_view)
    


  16. Decorators With Arguments

  17. @require_http_methods(["GET", "POST"])
    def example(request):
        return HttpResponse("This view accepts only GET and POST")
    


  18. Using Multiple Decorators

  19. from django.contrib.auth.decorators import login_required
    from django.views.decorators.http import require_GET
    
    @login_required
    @require_GET
    def profile(request):
        return HttpResponse("Your profile")
    


  20. Decorators and Class-Based Views (Beginner Note)



  21. Which Decorators Should Beginners Learn First?




File Uploads in Django (Beginner's Guide)

  1. What Does “File Upload” Mean in Django?



  2. Step 1: Configure MEDIA_ROOT and MEDIA_URL

  3. from pathlib import Path
    
    BASE_DIR = Path(__file__).resolve().parent.parent
    
    MEDIA_ROOT = BASE_DIR / "media"   # folder on disk for uploaded files
    MEDIA_URL  = "/media/"            # URL prefix used in the browser
    


  4. Step 2: Serve Media Files in Development

  5. from django.contrib import admin
    from django.urls import path, include
    from django.conf import settings
    from django.conf.urls.static import static
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("blog/", include("blog.urls")),
    ]
    
    if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    


  6. Step 3: Simple Upload Form (HTML)

  7. <!-- blog/templates/blog/upload.html -->
    
    <h1>Upload a File</h1>
    
    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <input type="file" name="file" />
        <br/><br/>
        <button type="submit">Upload</button>
    </form>
    


  8. Step 4: View That Saves the Uploaded File (Manual Saving)

  9. from django.shortcuts import render
    from django.http import HttpResponse
    from django.conf import settings
    import os
    
    def upload_file(request):
        if request.method == "POST":
            uploaded = request.FILES.get("file")
    
            if not uploaded:
                return HttpResponse("No file selected.")
    
            save_path = settings.MEDIA_ROOT / uploaded.name
    
            with open(save_path, "wb") as f:
                for chunk in uploaded.chunks():
                    f.write(chunk)
    
            return HttpResponse(f"Uploaded: {uploaded.name}")
    
        return render(request, "blog/upload.html")
    


  10. Step 5: URL for the Upload View

  11. from django.urls import path
    from . import views
    
    urlpatterns = [
        path("upload/", views.upload_file, name="upload"),
    ]
    


  12. Where Files Actually Go

  13. mysite/
    ├── manage.py
    ├── media/
    │   └── picture.jpg
    └── blog/
        ├── views.py
        └── ...
    


  14. Serving Uploaded Files (Manual Example)

  15. /media/picture.jpg
    
    <img src="/media/picture.jpg" alt="uploaded" />
    


  16. Using a Model with FileField (Recommended)

  17. # blog/models.py
    
    from django.db import models
    
    class Upload(models.Model):
        file = models.FileField(upload_to="uploads/")
    
        def __str__(self):
            return self.file.name
    
    media/
    └── uploads/
        └── myfile.pdf
    


  18. View That Uses the Model
  19. from django.shortcuts import render
    from django.http import HttpResponse
    from .models import Upload
    
    def upload_with_model(request):
        if request.method == "POST":
            file_obj = request.FILES.get("file")
            if not file_obj:
                return HttpResponse("No file selected.")
    
            Upload.objects.create(file=file_obj)
            return HttpResponse("File uploaded using model!")
    
        return render(request, "blog/upload.html")
    


  20. Listing and Displaying Uploaded Files
  21. def show_uploads(request):
        files = Upload.objects.all()
        return render(request, "blog/files.html", {"files": files})
    
    <!-- blog/templates/blog/files.html -->
    
    <h2>Uploaded Files</h2>
    
    {% for f in files %}
        <p>
            <a href="{{ f.file.url }}">{{ f.file.name }}</a>
        </p>
    {% endfor %}
    


  22. Serving Media Files: Development vs Production

  23. from django.conf import settings
    from django.conf.urls.static import static
    
    urlpatterns = [
        # your normal routes here...
    ]
    
    if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    

    location /media/ {
        alias /var/www/myproject/media/;
    }
    


  24. Common Beginner Mistakes (Revisited)



  25. Summary




Django Shortcut HTTP Functions (Beginner's Guide)

  1. What Are Django Shortcut HTTP Functions?



  2. render() — Return an HTML Template

  3. from django.shortcuts import render
    
    def home(request):
        context = {"title": "Homepage"}
        return render(request, "blog/home.html", context)
    
    from django.template import loader
    from django.http import HttpResponse
    
    def home(request):
        template = loader.get_template("blog/home.html")
        html = template.render({"title": "Homepage"}, request)
        return HttpResponse(html)
    


  4. redirect() — Redirect the User to Another URL

  5. from django.shortcuts import redirect
    
    def go_home(request):
        return redirect("/blog/home/")
    
    def go_home(request):
        return redirect("home")   # the URL pattern named "home"
    


  6. get_object_or_404() — Retrieve an Object or Return 404

  7. from django.shortcuts import get_object_or_404
    from .models import Post
    
    def show_post(request, id):
        post = get_object_or_404(Post, pk=id)
        return render(request, "blog/post.html", {"post": post})
    
    try:
        post = Post.objects.get(pk=id)
    except Post.DoesNotExist:
        raise Http404()
    


  8. 4. get_list_or_404() — Get a List or Return 404

  9. from django.shortcuts import get_list_or_404
    from .models import Post
    
    def posts_by_author(request, name):
        posts = get_list_or_404(Post, author=name)
        return render(request, "blog/list.html", {"posts": posts})
    


  10. HttpResponse() — Return Plain Text or Custom Content

  11. from django.http import HttpResponse
    
    def hello(request):
        return HttpResponse("Hello world!")
    
    return HttpResponse("Not allowed", status=405)
    


  12. HttpResponseRedirect() — Redirect Using a URL

  13. from django.http import HttpResponseRedirect
    
    def go_somewhere(request):
        return HttpResponseRedirect("/blog/home/")
    


  14. JsonResponse() — Return JSON Data

  15. from django.http import JsonResponse
    
    def api_data(request):
        return JsonResponse({"name": "Junzhe", "age": 22})
    


  16. HttpResponseNotFound(), HttpResponseForbidden(), etc.

  17. from django.http import HttpResponseNotFound
    
    def missing(request):
        return HttpResponseNotFound("This page does not exist")
    



Beginner's Guide to Django Generic Views

  1. What Are Generic Views?



  2. The Two Most Common Generic Views



  3. ListView — Display a List of Objects

  4. # blog/models.py
    
    from django.db import models
    
    class Post(models.Model):
        title = models.CharField(max_length=200)
        body = models.TextField()
    
        def __str__(self):
            return self.title
    
    # blog/views.py
    
    from django.views.generic import ListView
    from .models import Post
    
    class PostListView(ListView):
        model = Post
        template_name = "blog/post_list.html"
    
    # blog/urls.py
    
    from django.urls import path
    from .views import PostListView
    
    urlpatterns = [
        path("posts/", PostListView.as_view(), name="post-list"),
    ]
    
    <!-- blog/templates/blog/post_list.html -->
    
    <h1>All Posts</h1>
    
    {% for post in object_list %}
        <h3>{{ post.title }}</h3>
        <p>{{ post.body|truncatechars:80 }}</p>
    {% endfor %}
    


  5. DetailView — Show One Object

  6. # blog/views.py
    
    from django.views.generic import DetailView
    
    class PostDetailView(DetailView):
        model = Post
        template_name = "blog/post_detail.html"
    
    # blog/urls.py
    
    from .views import PostDetailView
    
    urlpatterns += [
        path("posts/<int:pk>/", PostDetailView.as_view(), name="post-detail"),
    ]
    
    <!-- blog/templates/blog/post_detail.html -->
    
    <h1>{{ object.title }}</h1>
    <p>{{ object.body }}</p>
    


  7. Understanding `pk` in the URL



  8. Other Useful Generic Views (Beginner Overview)


  9. from django.views.generic import CreateView
    from .models import Post
    
    class PostCreateView(CreateView):
        model = Post
        fields = ["title", "body"]
        template_name = "blog/post_form.html"
        success_url = "/blog/posts/"
    


  10. How Generic Views Know What to Do



  11. Customizing Context Data

  12. class PostListView(ListView):
        model = Post
        template_name = "blog/post_list.html"
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context["extra"] = "Hello from context!"
            return context
    
    {{ extra }}



Beginner's Guide to Django Middleware

  1. What Is Middleware?



  2. Where Is Middleware Defined?

  3. # mysite/settings.py
    
    MIDDLEWARE = [
        "django.middleware.security.SecurityMiddleware",
        "django.contrib.sessions.middleware.SessionMiddleware",
        "django.middleware.common.CommonMiddleware",
        "django.middleware.csrf.CsrfViewMiddleware",
        "django.contrib.auth.middleware.AuthenticationMiddleware",
        "django.contrib.messages.middleware.MessageMiddleware",
        "django.middleware.clickjacking.XFrameOptionsMiddleware",
    ]
    


  4. How Middleware Works (Simple Explanation)

  5. Request → Middleware 1 → Middleware 2 → ... → View
    Response ← Middleware 1 ← Middleware 2 ← ... ← View
    


  6. Django’s Most Important Built-In Middleware (Beginner-Friendly)



  7. Writing Your First Custom Middleware

  8. # blog/middleware.py
    
    class SimpleLogMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            print("A request just arrived!")
    
            response = self.get_response(request)
    
            print("A response is leaving!")
            return response
    
    MIDDLEWARE += [
        "blog.middleware.SimpleLogMiddleware",
    ]
    


  9. Middleware That Runs Before the View

  10. class CheckAdminMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            return self.get_response(request)
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print(f"About to call: {view_func.__name__}")
    


  11. Middleware That Runs After the View

  12. class AddHeaderMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            response = self.get_response(request)
            response["X-My-Header"] = "Hello"
            return response
    


  13. Key Rules to Remember




Beginner's Guide to Using Sessions in Django

  1. What Are Sessions in Django?



  2. How Sessions Work (Beginner Explanation)


  3. request.session
    


  4. Check That Sessions Are Enabled



  5. Storing Data in a Session

  6. def set_session(request):
        request.session["username"] = "Junzhe"
        request.session["role"] = "admin"
        return HttpResponse("Session data saved!")
    


  7. Retrieving Data from a Session
  8. def get_session(request):
        username = request.session.get("username", "Guest")
        return HttpResponse(f"Hello {username}!")
    


  9. Checking If a Session Key Exists
  10. if "username" in request.session:
        ...
    


  11. Deleting a Single Session Key
  12. def delete_key(request):
        if "username" in request.session:
            del request.session["username"]
        return HttpResponse("Username deleted.")
    


  13. Clearing the Entire Session

  14. request.session.flush()
    


  15. Setting Session Expiration

  16. request.session.set_expiry(60 * 60)  # 1 hour
    
    request.session.set_expiry(None)
    
    request.session.set_expiry(0)
    


  17. Where Does Django Store Session Data?

  18. django_session
    


  19. Example: Simple Page Visit Counter

  20. def counter(request):
        count = request.session.get("count", 0)
        request.session["count"] = count + 1
        return HttpResponse(f"You have visited this page {count} times.")
    


  21. How Sessions Relate to Authentication



  22. Quick Checklist for Beginners



  23. Summary




Django Template Language

  1. What Is a Django Template?



  2. Where Templates Live in Your Project

  3. mysite/
    ├── manage.py
    ├── mysite/
    │   ├── settings.py
    │   └── urls.py
    └── blog/
        ├── views.py
        ├── models.py
        └── templates/
            └── blog/
                └── home.html
    
    TEMPLATES = [
        {
            "BACKEND": "django.template.backends.django.DjangoTemplates",
            "DIRS": [],          # extra global template folders (optional)
            "APP_DIRS": True,    # <-- search in app/templates/
            "OPTIONS": {
                "context_processors": [
                    # default processors...
                ],
            },
        },
    ]
    


  4. Rendering a Template from a View

  5. from django.shortcuts import render
    
    def home(request):
        context = {
            "name": "Junzhe",
            "age": 22,
        }
        return render(request, "blog/home.html", context)
    
    <!-- blog/templates/blog/home.html -->
    <h1>Hello {{ name }}!</h1>
    <p>You are {{ age }} years old.</p>
    


  6. Template Variables: {{ ... }}

  7. <p>User: {{ username }}</p>
    <p>Today is {{ current_date }}</p>
    
    <p>Title: {{ post.title }}</p>
    <p>Author: {{ post.author.username }}</p>
    <p>First tag: {{ post.tags.0 }}</p>
    


  8. Template Filters: {{ variable|filter }}

  9. <p>Original: {{ username }}</p>
    <p>Uppercase: {{ username|upper }}</p>
    <p>Lowercase: {{ username|lower }}</p>
    <p>Length: {{ username|length }}</p>
    <p>Default if empty: {{ nickname|default:"No nickname" }}</p>
    


  10. Template Tags: {% ... %}



  11. The {% if %} Tag (Conditions)

  12. {% if user_is_logged_in %}
        <p>Welcome back!</p>
    {% endif %}
    
    {% if user.is_authenticated %}
        <p>Hello {{ user.username }}!</p>
    {% else %}
        <p>You are not logged in.</p>
    {% endif %}
    
    {% if score >= 90 %}
        <p>Grade: A</p>
    {% elif score >= 80 %}
        <p>Grade: B</p>
    {% else %}
        <p>Keep trying!</p>
    {% endif %}
    


  13. The {% for %} Tag (Loops)

  14. <ul>
    {% for post in posts %}
        <li>{{ post.title }}</li>
    {% endfor %}
    </ul>
    
    {% for item in items %}
        <p>{{ forloop.counter }}. {{ item }}</p>
    {% endfor %}
    


  15. {% url %} Tag (Reverse URL Resolution)

  16. path("hello/", views.hello, name="hello")
    
    <a href="{% url 'hello' %}">Say Hello</a>
    
    path("post/<int:pk>/", views.post_detail, name="post-detail")
    
    <a href="{% url 'post-detail' pk=post.id %}">Read more</a>
    


  17. Template Comments: {# ... #}

  18. {# This is a Django template comment #}
    <p>Visible to user</p>
    


  19. Template Inheritance: {% extends %} and {% block %}

  20. <!-- blog/templates/blog/base.html -->
    <!doctype html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>My Site - {% block title %}Default Title{% endblock %}</title>
    </head>
    <body>
        <header>
            <h1>My Blog</h1>
        </header>
    
        <main>
            {% block content %}{% endblock %}
        </main>
    
        <footer>
            <p>Copyright 2025</p>
        </footer>
    </body>
    </html>
    
    <!-- blog/templates/blog/home.html -->
    {% extends "blog/base.html" %}
    
    {% block title %}Home{% endblock %}
    
    {% block content %}
        <h2>Welcome!</h2>
        <p>This is the home page.</p>
    {% endblock %}
    


  21. {% include %} for Reusing Small Pieces

  22. <!-- blog/templates/blog/nav.html -->
    <nav>
        <a href="{% url 'home' %}">Home</a>
        <a href="{% url 'post-list' %}">Posts</a>
    </nav>
    
    <!-- in base.html -->
    <body>
        {% include "blog/nav.html" %}
        <main>
            {% block content %}{% endblock %}
        </main>
    </body>
    


  23. Static Files in Templates: {% load static %}

  24. {% load static %}
    
    <link rel="stylesheet" href="{% static 'css/style.css' %}" />
    <img src="{% static 'images/logo.png' %}" alt="Logo" />
    


  25. Auto-Escaping and Safety

  26. {{ user_input }}
    
    &lt;script&gt;alert('xss')&lt;/script&gt;
    
    {{ html_content|safe }}
    


  27. Context: What Data Is Available in Templates?

  28. return render(request, "blog/home.html", {"name": "Junzhe"})
    
    {% if user.is_authenticated %}
        <p>Logged in as {{ user.username }}</p>
    {% else %}
        <p>Not logged in</p>
    {% endif %}
    


  29. Template Language Limitations (On Purpose)



  30. Custom Template Filters and Tags (Very Brief Intro)

  31. blog/
    ├── templatetags/
    │   ├── __init__.py
    │   └── blog_extras.py
    
    # blog/templatetags/blog_extras.py
    
    from django import template
    
    register = template.Library()
    
    @register.filter
    def shout(value):
        return str(value).upper() + "!!!"
    
    {% load blog_extras %}
    
    <p>{{ "hello"|shout }}</p>  {# outputs HELLO!!! #}
    



Django URL Mapping

  1. What Is URL Mapping in Django?



  2. The URL Dispatcher



  3. Project-Level urls.py



  4. App-Level urls.py



  5. Understanding path() Parameters



  6. Using URL Parameters



  7. Using re_path() for Regular Expressions



  8. URL Names and Reverse Lookups



  9. Organizing URL Files (Recommended Structure)

  10. myproject/
        myproject/
            urls.py            <-- main router
        blog/
            urls.py            <-- app router
        accounts/
            urls.py
        shop/
            urls.py
    


  11. Including URLs Under a Common Prefix
  12. urlpatterns = [
        path('api/', include('api.urls')),
        path('auth/', include('accounts.urls')),
    ]
    


  13. Handling 404 and Error URLs
  14. 
    handler404 = 'myproject.views.page_not_found'
    handler500 = 'myproject.views.server_error'
    



Django Shell

  1. What Is the Django Shell?



  2. Starting the Django Shell



  3. Using the Enhanced Django Shell (shell_plus)



  4. Running Basic ORM Commands



  5. Checking Model Fields and Metadata



  6. Importing and Using Django Settings
  7. from django.conf import settings
    settings.DEBUG


  8. Testing Functions and Business Logic

  9. from accounts.utils import hash_password
    hash_password("secret123")


  10. Working With Transactions

  11. from django.db import transaction
    with transaction.atomic():
        Post.objects.create(title="Atomic", content="Safe commit!")


  12. Using the Shell for Debugging

  13. Post.objects.get(id=999)


  14. Loading Sample Data

  15. from django.contrib.auth.models import User
    User.objects.create_user("junzhe", password="1234")


  16. Exiting the Django Shell

  17. exit()
    Ctrl + D



Django Admin Interface

  1. What Is the Django Admin Interface?



  2. Enabling the Admin Interface



  3. Creating an Admin User



  4. Registering Models in the Admin



  5. Customizing ModelAdmin



  6. Custom Forms in Admin



  7. Using Fieldsets for Grouping Fields



  8. Admin Site Customization



  9. Permissions and Access Control



  10. Security Recommendations



Django Admin Create User

  1. Creating Users via Django Admin



  2. Fields in the Admin Create User Form



  3. Customizing the User Creation Form



  4. Creating Users Programmatically (Optional)



  5. Important Tips



Django Admin Include Models

  1. What Does "Including Models in Django Admin" Mean?



  2. Basic Model Registration



  3. Registering Multiple Models



  4. Using ModelAdmin for Custom Admin Behavior



  5. Grouping Models Under an App Label



  6. Customizing Display Names of Models



  7. Unregistering a Model



  8. Auto-Discovery of Admin Files



Django Admin Set Fields to Display

  1. What Does "Display Fields in Django Admin" Mean?



  2. Setting Fields for List Display



  3. Setting Fields in the Form View



  4. Making Fields Read-Only



  5. Controlling Which Fields Are Editable in List View



  6. Using Exclude to Hide Fields



  7. Dynamic Field Customization



  8. Hiding the Primary Key Field



Django Admin Update Objects

  1. What Does "Updating Objects in Django Admin" Mean?



  2. Accessing the Update Form



  3. Basic Object Updating



  4. Customizing Fields in the Update Form



  5. Making Certain Fields Read-Only



  6. Editing Related Objects (Inline Models)



  7. Bulk Updating Multiple Objects



  8. Tracking Who Updated an Object



  9. Preventing Users from Updating Objects



  10. Validating Object Updates