Django overview

Objectives: Full overiew

Django Full Notes

Complete Django Notes

Beginner to Advanced β€” Full Guide

1. Introduction to Django

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. It follows the MVT architecture (Model-View-Template).

  • Model β€” Handles the database (data structure).
  • View β€” Contains the logic and connects model to template.
  • Template β€” Handles HTML and presentation.

2. Setting up Django

  1. Install Python (recommended 3.12+).
  2. Create a Virtual Environment:
    python -m venv venv
    # Activate on Windows:
    venv\Scripts\activate
    # Activate on Mac/Linux:
    source venv/bin/activate
    
  3. Install Django:
    pip install django
  4. Check version:
    python -m django --version

3. Creating a Project

django-admin startproject mysite
cd mysite
python manage.py runserver

Visit http://127.0.0.1:8000 to see the default page.

4. Creating an App

python manage.py startapp blog

Register the app in mysite/settings.py under INSTALLED_APPS.

5. Models

Define your database structure in models.py:

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

6. Migrations

Apply database changes:

python manage.py makemigrations
python manage.py migrate

7. Django Admin

Create a superuser to access the admin panel:

python manage.py createsuperuser

Register models in admin.py:

from django.contrib import admin
from .models import Post

admin.site.register(Post)

Run server and go to /admin.

8. Views and URLs

Create a view in views.py:

from django.http import HttpResponse

def home(request):
    return HttpResponse("Hello, Django!")

Map it in urls.py:

from django.contrib import admin
from django.urls import path
from blog import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.home, name='home'),
]

9. Templates

Create a folder templates and an HTML file home.html:

<h1>Welcome to Django</h1>
<p>This is a template example</p>

Render it in views.py:

from django.shortcuts import render

def home(request):
    return render(request, 'home.html')

10. Static Files

For CSS/JS, create a static folder inside your app and load it in templates using:

{% load static %}
<link rel="stylesheet" href="{% static 'style.css' %}">

11. Deployment

  • Use a production server like Gunicorn or uWSGI.
  • Configure allowed hosts in settings.py.
  • Use a database like PostgreSQL for production.

12. Best Practices

  • Always use virtual environments.
  • Keep settings secret (use environment variables).
  • Write reusable apps.
  • Follow Django security recommendations.
Note: Always deactivate the virtual environment with deactivate when done.

Β© 2025 Django Full Notes | Created for Educational Purposes

Django Apps: Practical Notes with Vivid Examples

Django Apps: How, When, and Why (with Examples)

A practical, copy-pasteable guide to structuring real Django projects without creating unnecessary apps.

What is a Django App?

A Django app is a focused, self-contained package that implements one business capability (e.g., users, billing, news). A project can have many apps, and each app can be reused in another project.

Focused capability Reusable Testable Team-friendly

Why split into apps?

Pros

  • Maintainability: Smaller, easier-to-understand code units.
  • Reusability: Move an app to a new project without the rest.
  • Team collaboration: Parallel work with fewer conflicts.
  • Clear ownership: Each app has its own models, URLs, templates, tests.

Cons (if overdone)

  • Too many apps cause indirection and boilerplate.
  • Cross-app dependencies can tangle if boundaries are vague.
  • Context switching increases if you split tiny features prematurely.

Rule of Thumb: When to create a new app

SituationActionReason
Feature can stand alone & could be reused elsewhere Make a new app Portability and clean boundaries
Feature is tightly coupled to an existing app Don’t make a new app Keep cohesion; reduce boilerplate
Different domain/team owns the code Make a new app Ownership & parallel development
Tiny sub-feature (e.g., β€œprofile” under users) Keep in the users app Lower complexity

Recommended app lineup for a typical product

  • core/ β€” settings helpers, custom middleware, base templates, utilities.
  • users/ β€” registration, auth, profiles, permissions.
  • billing/ β€” plans, invoices, webhooks, subscriptions.
  • news/ β€” posts, categories, comments.
  • notifications/ β€” email/SMS/push queue, templates.
  • api/ β€” DRF viewsets/serializers/routers (only if you ship an API).

Project vs. App: Directory layout

myproject/
β”œβ”€ manage.py
β”œβ”€ pyproject.toml            # optional; or requirements.txt
β”œβ”€ myproject/                # project package (settings/urls/wsgi/asgi)
β”‚  β”œβ”€ __init__.py
β”‚  β”œβ”€ settings.py
β”‚  β”œβ”€ urls.py
β”‚  β”œβ”€ wsgi.py
β”‚  └─ asgi.py
β”œβ”€ core/                     # app
β”‚  β”œβ”€ apps.py
β”‚  β”œβ”€ admin.py
β”‚  β”œβ”€ models.py
β”‚  β”œβ”€ urls.py
β”‚  β”œβ”€ views.py
β”‚  β”œβ”€ templates/core/...
β”‚  β”œβ”€ static/core/...
β”‚  └─ tests/
β”œβ”€ users/                    # app
β”œβ”€ billing/                  # app
└─ news/                     # app

Creating and wiring an app (step-by-step)

  1. Generate the app:
    python manage.py startapp news
  2. Install it in settings.py:
    # myproject/settings.py
    INSTALLED_APPS = [
        "django.contrib.admin",
        "django.contrib.auth",
        ...
        "news",  # our app
    ]
  3. Give the app its own URLconf and include it in the project:
    # news/urls.py
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path("", views.NewsListView.as_view(), name="news_list"),
        path("<slug:slug>/", views.NewsDetailView.as_view(), name="news_detail"),
    ]
    # myproject/urls.py
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path("admin/", admin.site.urls),
        path("news/", include("news.urls")),
    ]

Vivid example: A minimal news app

Models

# news/models.py
from django.db import models
from django.contrib.auth import get_user_model

User = get_user_model()

class Category(models.Model):
    name = models.CharField(max_length=80, unique=True)
    slug = models.SlugField(max_length=100, unique=True)

    def __str__(self):
        return self.name

class Post(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=220, unique=True)
    category = models.ForeignKey(Category, on_delete=models.PROTECT, related_name="posts")
    author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
    body = models.TextField()
    published_at = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-published_at", "-created_at"]

    def __str__(self):
        return self.title

Views

# news/views.py
from django.views.generic import ListView, DetailView
from .models import Post

class NewsListView(ListView):
    model = Post
    template_name = "news/list.html"
    paginate_by = 10
    queryset = Post.objects.filter(published_at__isnull=False)

class NewsDetailView(DetailView):
    model = Post
    template_name = "news/detail.html"
    slug_field = "slug"
    slug_url_kwarg = "slug"

Templates


{% extends "base.html" %}
{% block content %}
  <h1>Latest News</h1>
  <ul>
  {% for post in object_list %}
    <li><a href="{% url 'news_detail' slug=post.slug %}">{{ post.title }}</a></li>
  {% empty %}
    <li>No posts yet.</li>
  {% endfor %}
  </ul>
{% endblock %}

Admin

# news/admin.py
from django.contrib import admin
from .models import Post, Category

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ("title", "category", "published_at")
    list_filter = ("category",)
    search_fields = ("title", "body")
    prepopulated_fields = {"slug": ("title",)}

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("name",)}

Migrations & database

# Create and apply migrations for your new app
python manage.py makemigrations news
python manage.py migrate

Example: A combined users app (auth + profile)

Instead of separate registeruser and profile apps, keep them together:

# users/models.py (using the default auth User with a Profile)
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
    avatar = models.ImageField(upload_to="avatars/", blank=True, null=True)
    bio = models.CharField(max_length=240, blank=True)

    def __str__(self):
        return f"Profile({self.user.username})"
# users/signals.py (auto-create a profile for new users)
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth import get_user_model
from .models import Profile

User = get_user_model()

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
# users/apps.py (connect signals on app ready)
from django.apps import AppConfig

class UsersConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "users"

    def ready(self):
        from . import signals  # noqa
# myproject/settings.py
INSTALLED_APPS = [
    ...,
    "users.apps.UsersConfig",
]

URL composition patterns

# project urls.py
urlpatterns = [
    path("admin/", admin.site.urls),
    path("users/", include("users.urls")),
    path("news/", include("news.urls")),
    path("billing/", include("billing.urls")),
]
# app urls.py (example)
from django.urls import path
from . import views

app_name = "billing"  # namespacing is good practice
urlpatterns = [
    path("checkout/", views.checkout, name="checkout"),
]

Cross-app interactions (keeping boundaries clean)

Scenario:

You need to show a user’s latest Post on their profile page.

Do (loose coupling):

# users/views.py
from django.shortcuts import render, get_object_or_404
from django.contrib.auth import get_user_model
User = get_user_model()

def profile(request, username):
    user = get_object_or_404(User, username=username)
    # Import inline (local) to avoid hard dependency loops
    from news.models import Post
    latest_post = Post.objects.filter(author=user, published_at__isnull=False).first()
    return render(request, "users/profile.html", {"user_obj": user, "latest_post": latest_post})

Don’t (tight coupling):

Hard-importing models at module top across many apps and calling deep internals everywhere.

Packaging a reusable app (e.g., news)

  1. Keep external settings out of the app; use Django settings with sensible defaults.
  2. Provide apps.py, urls.py, templates under templates/news/, static under static/news/.
  3. Add minimal dependencies; document installation.
# news/__init__.py
default_app_config = "news.apps.NewsConfig"  # optional on modern Django if using AppConfig path

# pyproject.toml (excerpt)
[project]
name = "django-news-lite"
version = "0.1.0"
dependencies = ["Django>=4.2"]
# Installing locally in another project (editable mode)
pip install -e /path/to/django-news-lite

Naming apps well

  • Prefer domain names: users, billing, news, inventory.
  • Avoid verbs or overly specific names like registeruser β€” use users and put registration inside it.
  • Keep names lowercase and singular/plural consistently.

Tests per app

# news/tests/test_views.py
import pytest
from django.urls import reverse
from news.models import Post

@pytest.mark.django_db
def test_news_list_view(client):
    url = reverse("news_list")
    resp = client.get(url)
    assert resp.status_code == 200

Common patterns that avoid β€œtoo many apps”

  • Combine micro-features: users = auth + profiles + passwords + invitations.
  • API stays inside domain app if small (e.g., news/api.py), or use a dedicated api app if you have many endpoints across domains.
  • Shared utilities go into core or common app.

Minimal β€œusers” app with signup (functional example)

# users/forms.py
from django import forms
from django.contrib.auth.models import User

class SignUpForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)
    class Meta:
        model = User
        fields = ["username", "email", "password"]

# users/views.py
from django.shortcuts import render, redirect
from django.contrib.auth import login
from .forms import SignUpForm

def signup(request):
    if request.method == "POST":
        form = SignUpForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            pwd = form.cleaned_data["password"]
            user.set_password(pwd)
            user.save()
            login(request, user)
            return redirect("news_list")
    else:
        form = SignUpForm()
    return render(request, "users/signup.html", {"form": form})

# users/urls.py
from django.urls import path
from .views import signup
urlpatterns = [path("signup/", signup, name="signup")]

{% extends "base.html" %}
{% block content %}
  <h1>Create account</h1>
  <form method="post">{% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Sign up</button>
  </form>
{% endblock %}

Admin, static, templates: keep them inside each app

  • Templates scoped: templates/<app_name>/...
  • Static files scoped: static/<app_name>/...
  • Admin registered in each app’s admin.py

Settings tips

# settings.py
INSTALLED_APPS = [
    "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes",
    "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles",
    "core", "users", "news", "billing",
]

TEMPLATES = [{
  "BACKEND": "django.template.backends.django.DjangoTemplates",
  "DIRS": [BASE_DIR / "templates"],  # for global base.html
  "APP_DIRS": True,                  # enables app templates discovery
  "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",
  ]},
}]

When one app is enough

Early prototypes or internal tools can live in a single app (e.g., app/) until boundaries appear. Later, extract modules into new apps.

Checklist before creating a new app

  • Can this feature be described as a distinct noun? If yes β†’ new app.
  • Will another project reuse it? If yes β†’ new app.
  • Does it need its own models/admin/templates/urls? If yes β†’ new app.
  • Is it tiny or tightly coupled? If yes β†’ keep it in the existing app.

Quick Q&A

Q: β€œRegister user, billing, news… separate apps for each? Won’t we get tired?”

A: Split by capability, not by every tiny sub-feature. Use users, billing, news. Keep register/profile inside users. You’ll stay productive without app explosion.

Copy-paste starter commands

# Create apps
python manage.py startapp core
python manage.py startapp users
python manage.py startapp billing
python manage.py startapp news

# Wire URLs
# myproject/urls.py
# path("users/", include("users.urls"))
# path("billing/", include("billing.urls"))
# path("news/", include("news.urls"))

# Migrate
python manage.py makemigrations
python manage.py migrate

# Run
python manage.py runserver

That’s itβ€”you now have a clean, scalable app layout without creating a new app for every tiny feature.

Reference Book: N/A

Author name: SIR H.A.Mwala Work email: biasharaboraofficials@gmail.com
#MWALA_LEARN Powered by MwalaJS #https://mwalajs.biasharabora.com
#https://educenter.biasharabora.com

:: 1.0::

β¬