🎸

Top 42 Django Interview Questions & Answers (2026)

42 Questions 21 Beginner 12 Intermediate 9 Advanced

About Django

Top 50 Django interview questions covering MVT architecture, ORM, views, templates, REST framework, authentication, signals, middleware, and deployment best practices. Companies hiring for Django roles test this knowledge at every stage — from first-round screens that check the basics to final-round conversations about real-world trade-offs.

What to Expect in a Django Interview

Expect a mix of conceptual and practical Django questions: clear definitions and core-concept checks for junior roles, hands-on scenario questions for mid-level roles, and architecture or trade-off discussions for senior roles. Interviewers usually move from foundational topics toward the kind of problems you'd actually face on the job.

How to Use This Guide

Work through the Django questions in order — Beginner, then Intermediate, then Advanced — so each concept builds on the last. Every question has its own page; bookmark the ones that trip you up and revisit them the day before your interview.

Curated by Tech Baithak Editorial Team  ·  Last updated: May 2026

Beginner 21 questions

Core concepts every Django developer must know.

01

What is Django?

Django is a high-level, open-source Python web framework that encourages rapid development and clean, pragmatic design. Created in 2003 by Adrian Holovaty and Simon Willison at the Lawrence Journal-World newspaper, it was open-sourced in 2005. Django follows the "batteries included" philosophy — it ships with nearly everything developers might want out of the box: an ORM, authentication, admin panel, URL routing, template engine, form handling, security features, and more. Key principles: DRY (Don't Repeat Yourself) — reuse code components; Convention over Configuration — sensible defaults reduce decision fatigue; MVT Architecture — Model, View, Template pattern. Django powers Instagram, Pinterest, Disqus, Mozilla, National Geographic, and many other high-traffic sites. It includes built-in protection against CSRF, XSS, SQL injection, and clickjacking. Django's ORM handles database access across PostgreSQL, MySQL, SQLite, and Oracle without writing raw SQL. The Django admin interface provides a free, fully functional CRUD interface for your models out of the box.

Open this question on its own page
02

What is the MVT architecture in Django?

Django follows the MVT (Model-View-Template) architectural pattern, which is a variation of the classic MVC: (1) Model: defines the data structure and handles database interactions. Each model class maps to a database table. Models contain fields (CharField, IntegerField, ForeignKey) and methods for business logic. Django's ORM translates model operations to SQL automatically; (2) View: contains the business logic — receives HTTP requests, processes data (querying models, applying logic), and returns HTTP responses. Views are Python functions or class-based views (CBVs). They decide WHAT data to show, not HOW to display it; (3) Template: handles presentation — HTML files with Django Template Language (DTL) for dynamic content rendering. Templates use variables ({{ variable }}), tags ({% if %}, {% for %}), and filters ({{ date|date:"M d, Y" }}). Request flow: Browser → URL Dispatcher (urls.py) → View (views.py) → Model (models.py) → Database → Model → View → Template → HTTP Response → Browser. MVT vs MVC: in MVC, the Controller handles input and coordinates the model and view. In Django's MVT, the framework itself acts as the Controller — URL dispatching routes to the appropriate View, which takes on the Controller's coordination role.

Open this question on its own page
03

What is Django ORM?

Django's ORM (Object-Relational Mapper) provides a high-level Python API for interacting with databases without writing raw SQL. Each Django Model class maps to a database table; each instance maps to a row. Basic model: class Article(models.Model): title = models.CharField(max_length=200) content = models.TextField() author = models.ForeignKey(User, on_delete=models.CASCADE) published_at = models.DateTimeField(auto_now_add=True) is_published = models.BooleanField(default=False) class Meta: ordering = ["-published_at"]. QuerySet API: Article.objects.all() # All articles Article.objects.filter(is_published=True) # Filtered Article.objects.exclude(author__is_active=False) # Excluded Article.objects.get(id=1) # Single or raises DoesNotExist Article.objects.create(title="Hello", content="...") Article.objects.filter(title__icontains="django") Article.objects.order_by("-published_at")[:10] Article.objects.values("title", "author__username") Article.objects.annotate(comment_count=Count("comments")) Article.objects.select_related("author") # JOIN for FK Article.objects.prefetch_related("tags") # Prefetch M2M. Lazy evaluation: QuerySets are lazy — SQL is only executed when data is actually needed (iterated, converted to list, printed, sliced). Chaining: Article.objects.filter(is_published=True).exclude(author__is_staff=True).order_by("-published_at")[:5]. Django supports PostgreSQL, MySQL, SQLite, and Oracle.

Open this question on its own page
04

What are Django migrations?

Django migrations are Django's version control system for database schema changes. When you modify models (add fields, change types, create new models), migrations record those changes and apply them to the database. Workflow: (1) Modify models.py (add a field, change a model); (2) python manage.py makemigrations — creates a migration file in app/migrations/ describing the changes; (3) python manage.py migrate — applies pending migrations to the database. Migration commands: python manage.py makemigrations — detect and create new migrations; python manage.py migrate — apply all pending; python manage.py migrate myapp 0003 — migrate to specific version; python manage.py showmigrations — list all migrations and applied status; python manage.py sqlmigrate myapp 0003 — show the SQL for a migration; python manage.py migrate myapp zero — revert all migrations for an app. Migration files: plain Python files with operations list: migrations.AddField(), migrations.RemoveField(), migrations.CreateModel(), migrations.RunSQL(). Data migrations: migrations.RunPython() for custom data manipulation during migration. Important: commit migration files to version control — they're part of your schema history. Squash migrations for cleaner history: python manage.py squashmigrations myapp 0001 0010.

Open this question on its own page
05

What is the Django admin interface?

Django's admin interface is an automatically generated, fully functional CRUD web interface for managing your application's data — one of Django's most celebrated features. It comes for free just by registering your models. Enabling admin: django.contrib.admin is included by default. Visit /admin/. Create a superuser: python manage.py createsuperuser. Registering a model: basic: admin.site.register(Article). Custom admin class: @admin.register(Article) class ArticleAdmin(admin.ModelAdmin): list_display = ("title", "author", "published_at", "is_published") list_filter = ("is_published", "author") search_fields = ("title", "content") list_editable = ("is_published",) date_hierarchy = "published_at" ordering = ("-published_at",) readonly_fields = ("created_at", "updated_at") fieldsets = ( ("Content", {"fields": ("title", "content")}), ("Publishing", {"fields": ("author", "is_published", "published_at"), "classes": ("collapse",)}) ) actions = ["make_published"] def make_published(self, request, queryset): queryset.update(is_published=True). Features: list view with sorting/filtering/search; detail edit view; inline related objects; bulk actions; history/audit log; pagination; customizable themes. Security: admin requires staff permission (is_staff=True). Fine-grained permissions per model (add, change, delete, view). Restrict to specific IP: use middleware or deploy on a separate port. Change default URL: admin.site.urls can be remapped.

Open this question on its own page
06

What are Django views — function-based vs class-based?

Django views receive HTTP requests and return HTTP responses. Two styles: Function-Based Views (FBV): simple Python functions. from django.shortcuts import render, get_object_or_404 from django.http import JsonResponse def article_detail(request, pk): article = get_object_or_404(Article, pk=pk, is_published=True) if request.method == "POST": # handle form submission pass return render(request, "articles/detail.html", {"article": article}). Pros: simple, explicit, easy to understand. Cons: code duplication for common patterns. Class-Based Views (CBV): use Python classes with HTTP method handlers. Django provides generic CBVs for common patterns: from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView class ArticleListView(ListView): model = Article template_name = "articles/list.html" context_object_name = "articles" paginate_by = 10 def get_queryset(self): return Article.objects.filter(is_published=True) class ArticleCreateView(LoginRequiredMixin, CreateView): model = Article fields = ["title", "content"] success_url = "/articles/". Generic CBVs: ListView, DetailView, CreateView, UpdateView, DeleteView, FormView, TemplateView, RedirectView, LoginView, LogoutView. Pros: reuse code via inheritance and mixins; less boilerplate for CRUD. Cons: can be harder to understand the flow. When to use each: FBVs for complex logic with many conditions; CBVs for standard CRUD and REST APIs. Mixins like LoginRequiredMixin, PermissionRequiredMixin add cross-cutting behavior.

Open this question on its own page
07

What is URL routing in Django?

Django's URL routing maps URL patterns to view functions/classes using Python regex or path converters. urls.py structure: from django.urls import path, include, re_path from . import views urlpatterns = [ path("", views.home, name="home"), path("articles/", views.ArticleListView.as_view(), name="article-list"), path("articles/<int:pk>/", views.ArticleDetailView.as_view(), name="article-detail"), path("articles/<slug:slug>/", views.article_by_slug, name="article-slug"), path("api/", include("api.urls")), # include another urls.py re_path(r"^legacy/(?P<id>\d+)/$", views.legacy_view), # regex ]. Path converters: <int:id> — integer; <str:name> — string (no slash); <slug:slug> — slug; <uuid:id> — UUID; <path:rest> — any string including slashes. Named URLs: name all URL patterns — use in views and templates: from django.urls import reverse; reverse("article-detail", kwargs={"pk": 1}). In templates: {% url "article-detail" pk=article.pk %}. Include: organize URLs in sub-apps: path("blog/", include("blog.urls")) — all blog app URLs prefixed with /blog/. Namespacing: app_name = "blog" in app's urls.py + include("blog.urls", namespace="blog"){% url "blog:article-detail" pk=1 %} avoids name collisions between apps. Main urls.py: urlpatterns = [path("admin/", admin.site.urls), path("", include("myapp.urls"))].

Open this question on its own page
08

What is Django Template Language (DTL)?

Django Template Language (DTL) is Django's built-in template engine for rendering HTML with dynamic data. Variables: {{ variable }} — renders the value; {{ user.username }} — attribute access; {{ dictionary.key }} — dict access; {{ list.0 }} — index access. Tags: {% if condition %}...{% elif %}...{% else %}...{% endif %}; {% for item in items %}{{ item.name }}{% empty %}No items{% endfor %}; {% url "view-name" arg1 arg2 %} — URL generation; {% include "partial.html" %} — include template; {% extends "base.html" %} — template inheritance; {% block content %}...{% endblock %} — define block for child templates; {% load staticfiles %}{% static "css/style.css" %} — static files; {% csrf_token %} — CSRF protection in forms. Filters: {{ name|lower }}; {{ text|truncatewords:30 }}; {{ date|date:"M d, Y" }}; {{ price|floatformat:2 }}; {{ html_content|safe }} — mark as safe (no escaping); {{ items|length }}; {{ value|default:"N/A" }}. Template inheritance: base.html defines blocks; child templates extend and fill them: {% extends "base.html" %}{% block title %}Article{% endblock %}{% block content %}<h1>{{ article.title }}</h1>{% endblock %}. DTL auto-escapes HTML by default — prevents XSS. Alternative: Jinja2 is also supported.

Open this question on its own page
09

What is Django REST Framework (DRF)?

Django REST Framework (DRF) is the most popular third-party library for building REST APIs with Django. It provides serialization, authentication, permissions, viewsets, routers, and browsable API. Installation: pip install djangorestframework; add "rest_framework" to INSTALLED_APPS. Serializer: converts complex data (querysets, model instances) to Python primitives (serializable to JSON/XML): from rest_framework import serializers class ArticleSerializer(serializers.ModelSerializer): author_name = serializers.CharField(source="author.get_full_name", read_only=True) class Meta: model = Article fields = ["id", "title", "content", "author_name", "published_at"] read_only_fields = ["id", "published_at"]. ViewSet: from rest_framework import viewsets, permissions class ArticleViewSet(viewsets.ModelViewSet): queryset = Article.objects.filter(is_published=True) serializer_class = ArticleSerializer permission_classes = [permissions.IsAuthenticatedOrReadOnly] def perform_create(self, serializer): serializer.save(author=self.request.user). Router (auto URL generation): router = DefaultRouter(); router.register("articles", ArticleViewSet); urlpatterns += router.urls. This creates: GET /articles/, POST /articles/, GET /articles/{id}/, PUT/PATCH /articles/{id}/, DELETE /articles/{id}/. Authentication: TokenAuthentication, SessionAuthentication, JWT (via simplejwt). Permissions: IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly, custom permissions. Pagination, filtering, throttling — all built-in.

Open this question on its own page
10

What is Django middleware?

Django middleware is a framework of hooks into Django's request/response processing. Each middleware component processes requests before they reach the view and responses before they leave Django. Middleware is applied in the order defined in MIDDLEWARE (request phase: top-to-bottom; response phase: bottom-to-top). Built-in middleware: SecurityMiddleware — HTTPS redirect, security headers; SessionMiddleware — session support; CommonMiddleware — URL normalization, APPEND_SLASH; CsrfViewMiddleware — CSRF protection; AuthenticationMiddleware — attaches user to request; MessageMiddleware — flash messages; XFrameOptionsMiddleware — clickjacking protection. Custom middleware: class RequestLoggingMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): import time start = time.time() response = self.get_response(request) duration = time.time() - start logger.info(f"{request.method} {request.path} {response.status_code} {duration:.3f}s") return response def process_exception(self, request, exception): logger.error(f"Exception in {request.path}: {exception}") # return None to let default handler proceed. Hooks: __call__ — processes request AND response; process_view(request, view_func, view_args, view_kwargs) — before the view; process_exception(request, exception) — when view raises exception; process_template_response(request, response) — when response has a context. Register in settings: MIDDLEWARE = ["myapp.middleware.RequestLoggingMiddleware", ...].

Open this question on its own page
11

What is Django authentication system?

Django includes a comprehensive authentication system in django.contrib.auth: User model: built-in User with fields: username, password (hashed with PBKDF2 by default), email, first_name, last_name, is_staff, is_active, is_superuser, last_login. Custom User model (recommended): extend AbstractUser or AbstractBaseUser before any migrations: from django.contrib.auth.models import AbstractUser class CustomUser(AbstractUser): phone = models.CharField(max_length=20, blank=True) avatar = models.ImageField(upload_to="avatars/", blank=True) AUTH_USER_MODEL = "myapp.CustomUser". Login/logout: from django.contrib.auth import authenticate, login, logout user = authenticate(request, username=u, password=p) if user: login(request, user) # saves user in session. Decorators: @login_required(login_url="/login/") def my_view(request): .... Permissions: model-level permissions auto-created (add, change, delete, view); custom permissions: class Meta: permissions = [("publish_article", "Can publish articles")]; check: request.user.has_perm("blog.publish_article"). Groups: assign multiple permissions to a group, assign users to groups. Password management: PBKDF2+SHA256 by default; check_password(), set_password(); password hashers configurable; password_reset views included. LoginView, LogoutView, PasswordChangeView — built-in class-based views. AllAuth: popular third-party for social auth (Google, GitHub, etc.).

Open this question on its own page
12

What are Django signals?

Django signals are a lightweight notification system allowing certain senders to notify a set of receivers when specific actions occur — decoupling components. Built-in signals: pre_save, post_save — before/after model save; pre_delete, post_delete — before/after model delete; m2m_changed — ManyToMany changes; request_started, request_finished — HTTP request lifecycle; user_logged_in, user_logged_out, user_login_failed. Connecting a receiver: from django.db.models.signals import post_save from django.dispatch import receiver from django.contrib.auth.models import User @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): if created: Profile.objects.create(user=instance) @receiver(post_save, sender=User) def send_welcome_email(sender, instance, created, **kwargs): if created: send_email.delay(instance.email, "Welcome!") # async. Register in AppConfig.ready(): class MyAppConfig(AppConfig): def ready(self): import myapp.signals # import to register. Custom signals: from django.dispatch import Signal order_placed = Signal() # Emit: order_placed.send(sender=Order, order=order_instance) # Receive: @receiver(order_placed) def handle_order(sender, order, **kwargs): send_confirmation_email(order). Caution: signals execute synchronously in the same transaction — keep handlers fast; use Celery for async work. Avoid complex signal chains — they're hard to trace. Prefer direct method calls when the relationship is clear.

Open this question on its own page
13

What is Django forms?

Django's forms system handles HTML form rendering, data validation, and cleaning. Two types: Form: standalone form: from django import forms class ContactForm(forms.Form): name = forms.CharField(max_length=100, widget=forms.TextInput(attrs={"class": "form-control"})) email = forms.EmailField() message = forms.CharField(widget=forms.Textarea(attrs={"rows": 5})) rating = forms.IntegerField(min_value=1, max_value=5) agree_terms = forms.BooleanField() def clean_email(self): email = self.cleaned_data["email"] if User.objects.filter(email=email).exists(): raise forms.ValidationError("Email already registered.") return email def clean(self): # Cross-field validation cleaned = super().clean() return cleaned. ModelForm: auto-generates form from model: class ArticleForm(forms.ModelForm): class Meta: model = Article fields = ["title", "content", "tags"] exclude = ["author"] widgets = {"content": forms.Textarea(attrs={"rows": 20})}. View usage: def create_article(request): if request.method == "POST": form = ArticleForm(request.POST, request.FILES) if form.is_valid(): article = form.save(commit=False); article.author = request.user; article.save(); return redirect("article-list") else: form = ArticleForm() return render(request, "create.html", {"form": form}). Template rendering: {{ form.as_p }}, {{ form.as_table }}, or individual fields: {{ form.title.label_tag }}{{ form.title }}{{ form.title.errors }}. Validation: field-level (clean_fieldname()), form-level (clean()). form.cleaned_data contains validated data.

Open this question on its own page
14

What is Django caching?

Django's caching framework stores expensive computations or database query results for faster subsequent access. Cache backends: Memcached (django.core.cache.backends.memcached.PyMemcacheCache), Redis (django_redis.cache.RedisCache), Database (django.core.cache.backends.db.DatabaseCache), File system, Local memory (development only). Configuration (Redis example): CACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"}, "TIMEOUT": 300}}. Cache API: from django.core.cache import cache cache.set("key", value, timeout=3600) cache.get("key") cache.get("key", default="fallback") cache.delete("key") cache.set_many({"k1": v1, "k2": v2}) cache.get_many(["k1", "k2"]) cache.incr("view_count") cache.clear(). Per-view caching: @cache_page(60 * 15) # Cache 15 minutes def my_view(request): .... Template fragment caching: {% load cache %}{% cache 900 sidebar request.user.id %}...{% endcache %}. Low-level caching pattern: def get_user_stats(user_id): key = f"user_stats_{user_id}"; result = cache.get(key) if result is None: result = expensive_query(user_id); cache.set(key, result, 3600) return result. Cache versioning and invalidation: use cache.delete() on data changes or use versioned keys.

Open this question on its own page
15

What is Django settings and configuration?

Django's settings.py is the central configuration file. Key settings: DEBUG = False # Never True in production SECRET_KEY = env("SECRET_KEY") # From environment ALLOWED_HOSTS = ["yourdomain.com", "www.yourdomain.com"] INSTALLED_APPS = ["django.contrib.admin", "django.contrib.auth", ..., "myapp"] DATABASES = {"default": {"ENGINE": "django.db.backends.postgresql", "NAME": env("DB_NAME"), "USER": env("DB_USER"), "PASSWORD": env("DB_PASSWORD"), "HOST": "localhost", "PORT": "5432"}} STATIC_URL = "/static/" STATIC_ROOT = BASE_DIR / "staticfiles" MEDIA_URL = "/media/" MEDIA_ROOT = BASE_DIR / "media" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" AUTH_USER_MODEL = "accounts.User" LOGIN_URL = "/login/" LOGIN_REDIRECT_URL = "/dashboard/" EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST = "smtp.sendgrid.net". Multiple settings files: split into base.py, development.py, production.py: python manage.py runserver --settings=config.settings.development or set DJANGO_SETTINGS_MODULE env var. Environment variables: use django-environ or python-decouple: import environ; env = environ.Env(); env.read_env(). Security settings for production: SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_HSTS_SECONDS = 31536000 SECURE_CONTENT_TYPE_NOSNIFF = True X_FRAME_OPTIONS = "DENY". CORS: use django-cors-headers: CORS_ALLOWED_ORIGINS = ["https://frontend.example.com"].

Open this question on its own page
16

What is Django static files and media files?

Django handles two types of files: Static files: CSS, JavaScript, images that are part of the codebase — versioned and deployed with the application. Configuration: STATIC_URL = "/static/" STATICFILES_DIRS = [BASE_DIR / "static"] # Development static files STATIC_ROOT = BASE_DIR / "staticfiles" # Collected output for production. Development: Django's dev server serves static files automatically. Production: collect all static files: python manage.py collectstatic — copies all static files to STATIC_ROOT. Serve via Nginx, WhiteNoise (pip install whitenoise — serves directly from Django), or CDN. Template usage: {% load static %}<link rel="stylesheet" href="{% static "css/style.css" %}">. Media files: user-uploaded content (profile pictures, document uploads) — not versioned with code, must persist between deployments. Configuration: MEDIA_URL = "/media/" MEDIA_ROOT = BASE_DIR / "media". Development: add URL to urls.py: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT). Production: serve via Nginx or store on cloud (S3 with django-storages). File upload in model: avatar = models.ImageField(upload_to="avatars/", null=True, blank=True) document = models.FileField(upload_to="docs/%Y/%m/"). Access: user.avatar.url, user.avatar.name, user.avatar.size. django-storages: DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" — store uploads to S3.

Open this question on its own page
17

What is select_related and prefetch_related in Django?

Both methods optimize database queries for related objects, preventing the N+1 query problem: select_related: performs a SQL JOIN to fetch related objects in a single query. Works with ForeignKey and OneToOneField (forward relationships). articles = Article.objects.select_related("author", "category").all() — one SQL query with JOIN instead of N queries. Access: article.author.username (no extra query). Use for "to-one" relationships. prefetch_related: performs separate queries for each relationship and does Python-level joining. Works with ManyToManyField and reverse ForeignKey (one-to-many). articles = Article.objects.prefetch_related("tags", "comments").all() — 3 queries: one for articles, one for tags, one for comments. Django joins them in Python. Prefetch objects: customize prefetch queries: from django.db.models import Prefetch active_comments = Prefetch("comments", queryset=Comment.objects.filter(is_approved=True), to_attr="active_comments") articles = Article.objects.prefetch_related(active_comments). Access: article.active_comments. N+1 problem example: for article in Article.objects.all(): # N+1! print(article.author.username) # Extra query per article. Fix: Article.objects.select_related("author").all() — one query. Diagnosing: use Django Debug Toolbar to see all queries executed per request. Combination: Article.objects.select_related("author").prefetch_related("tags")

Open this question on its own page
18

What is Django Q objects for complex queries?

Django's Q objects allow building complex queries with OR conditions, negation, and combinations that can't be expressed by chaining .filter() calls (which always produce AND conditions). Q object basics: from django.db.models import Q # OR condition: articles = Article.objects.filter(Q(title__icontains="django") | Q(content__icontains="django")) # AND condition (same as chaining .filter()): articles = Article.objects.filter(Q(is_published=True) & Q(author=request.user)) # NOT condition: articles = Article.objects.filter(~Q(status="draft")) # Complex combination: articles = Article.objects.filter( (Q(title__icontains="python") | Q(tags__name="python")) & Q(is_published=True) & ~Q(author__is_banned=True) ). Dynamic query building: def search_articles(terms, published_only=True): q = Q() for term in terms: q |= Q(title__icontains=term) | Q(content__icontains=term) if published_only: q &= Q(is_published=True) return Article.objects.filter(q). F objects (field references): reference another field in the query: from django.db.models import F # Find articles where likes > views Article.objects.filter(likes__gt=F("views")) # Atomic field update: Article.objects.filter(pk=1).update(view_count=F("view_count") + 1) # Compare two fields: Article.objects.filter(updated_at__gt=F("created_at")). F objects prevent race conditions in updates — the increment happens at the database level atomically.

Open this question on its own page
19

What is Django's request/response cycle?

Django's request/response cycle processes every HTTP request through a defined pipeline: (1) Web server receives request: Nginx/Apache forwards to Django via WSGI (Gunicorn, uWSGI) or ASGI (Daphne, Uvicorn for async). (2) WSGI/ASGI handler: creates an HttpRequest object from the raw request with: method (GET/POST), path, headers, GET/POST/FILES data, session, user (via middleware), META. (3) Middleware (request phase): each middleware in MIDDLEWARE list processes the request top-to-bottom. SecurityMiddleware, SessionMiddleware, AuthenticationMiddleware add data to request. Any middleware can short-circuit by returning a response. (4) URL resolver: matches request.path against urlpatterns. Finds the matching view function/class. Extracts URL parameters. Raises 404 if no match. (5) View: receives request + URL parameters. Queries models, applies business logic. Returns an HttpResponse (or raises Http404, PermissionDenied, etc.). (6) Middleware (response phase): each middleware processes the response in reverse order (bottom-to-top). (7) Response sent to client: HttpResponse has status_code, headers, content. (8) HttpRequest attributes: request.method, request.GET (QueryDict), request.POST (QueryDict), request.FILES, request.user (AnonymousUser if not authenticated), request.session (dict-like), request.META (server vars: REMOTE_ADDR, HTTP_USER_AGENT), request.COOKIES, request.path, request.is_ajax() (deprecated — check header).

Open this question on its own page
20

What is Django's manage.py and useful commands?

Django's manage.py is the command-line utility for administrative tasks. Run: python manage.py command. Essential commands: python manage.py runserver [port] — start development server (default 127.0.0.1:8000); python manage.py runserver 0.0.0.0:8080 — accessible on network; python manage.py makemigrations [appname] — create migration files; python manage.py migrate [appname] [migration] — apply migrations; python manage.py createsuperuser — create admin user; python manage.py shell — interactive Python shell with Django context; python manage.py shell_plus (django-extensions) — auto-imports all models; python manage.py dbshell — database shell (psql, mysql); python manage.py collectstatic — collect static files; python manage.py test [appname] — run tests; python manage.py test myapp.tests.TestCase.test_method — specific test; python manage.py loaddata fixture.json — load fixture data; python manage.py dumpdata myapp.Article --indent=2 > articles.json — export data; python manage.py check — system checks (missing fields, deprecated settings); python manage.py showmigrations; python manage.py sqlmigrate myapp 0001 — show SQL; python manage.py startapp appname — create new app. Custom management commands: create myapp/management/commands/my_command.py with a Command class extending BaseCommand. Run: python manage.py my_command --option value.

Open this question on its own page
21

What are Django model field types?

Django provides many model field types mapping to database column types: String fields: CharField(max_length=200) — VARCHAR; TextField() — TEXT (unlimited); EmailField() — CharField with email validator; URLField(); SlugField() — URL-friendly slug; UUIDField(default=uuid.uuid4). Numeric fields: IntegerField(); BigIntegerField(); PositiveIntegerField(); FloatField(); DecimalField(max_digits=10, decimal_places=2) — for money; SmallIntegerField(). Boolean: BooleanField(default=False); NullBooleanField() (deprecated — use BooleanField(null=True)). Date/Time: DateField(auto_now_add=True) — set on creation; DateTimeField(auto_now=True) — update on every save; TimeField(); DurationField(). File: FileField(upload_to="uploads/"); ImageField(upload_to="images/") — requires Pillow. Choice fields: CharField(max_length=10, choices=[("draft","Draft"),("published","Published")]). Relationship fields: ForeignKey(User, on_delete=models.CASCADE, related_name="articles"); ManyToManyField(Tag, blank=True); OneToOneField(User, on_delete=models.CASCADE). JSON: JSONField(default=dict) — native JSON storage (PostgreSQL, MySQL 8+, SQLite 3.9+). Generic relations: GenericForeignKey — polymorphic FK. Common options: null=True (database NULL), blank=True (form validation), default=value, unique=True, db_index=True, verbose_name="Human Name".

Open this question on its own page
Intermediate 12 questions

Practical knowledge for developers with hands-on experience.

01

What is Django DRF serializers in depth?

DRF serializers handle converting between complex data types and Python primitives (for JSON/XML rendering). Serializer types: Serializer (manual field declaration), ModelSerializer (auto from model), HyperlinkedModelSerializer (uses URLs instead of PKs). Validation: class UserSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True, min_length=8) confirm_password = serializers.CharField(write_only=True) class Meta: model = User fields = ["id", "email", "username", "password", "confirm_password"] def validate_email(self, value): if User.objects.filter(email=value).exists(): raise serializers.ValidationError("Email already in use") return value.lower() def validate(self, data): if data["password"] != data.pop("confirm_password"): raise serializers.ValidationError("Passwords don't match") return data def create(self, validated_data): return User.objects.create_user(**validated_data). Nested serializers: class ArticleSerializer(serializers.ModelSerializer): author = UserSerializer(read_only=True) tags = TagSerializer(many=True, read_only=True). SerializerMethodField: word_count = serializers.SerializerMethodField() def get_word_count(self, obj): return len(obj.content.split()). Source: author_name = serializers.CharField(source="author.get_full_name"). Depth: class Meta: depth = 1 — auto-serialize nested relations. Custom write behavior: override create() and update() for complex saving logic. to_representation: override to customize serialized output per instance.

Open this question on its own page
02

What is Django DRF authentication and permissions?

DRF provides pluggable authentication and permission systems: Authentication classes determine "who is the user?" REST_FRAMEWORK = {"DEFAULT_AUTHENTICATION_CLASSES": ["rest_framework.authentication.SessionAuthentication", "rest_framework_simplejwt.authentication.JWTAuthentication", "rest_framework.authentication.BasicAuthentication"]}. Authentication is per-view or global. Provides request.user and request.auth. JWT with simplejwt: pip install djangorestframework-simplejwt. Endpoints: POST /token/ returns access + refresh tokens; POST /token/refresh/ refreshes access token. Custom JWT payload: class MyTokenObtainPairSerializer(TokenObtainPairSerializer): @classmethod def get_token(cls, user): token = super().get_token(user); token["name"] = user.get_full_name(); token["role"] = user.role; return token. Permission classes determine "can this user do this?" class IsOwnerOrReadOnly(BasePermission): def has_object_permission(self, request, view, obj): if request.method in SAFE_METHODS: return True return obj.author == request.user. Per-view permission: permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]. Built-in permissions: AllowAny, IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly, DjangoModelPermissions, DjangoObjectPermissions. Throttling: rate limiting — DEFAULT_THROTTLE_RATES = {"anon": "100/day", "user": "1000/day"}. Filtering: pip install django-filter; integrate with DjangoFilterBackend.

Open this question on its own page
03

What are Django model relationships in depth?

Django ORM supports three types of model relationships: ForeignKey (Many-to-One): class Article(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="articles") category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True). on_delete options: CASCADE (delete children), PROTECT (prevent deletion if children exist), SET_NULL (set FK to null), SET_DEFAULT, DO_NOTHING. Access: article.author (forward), user.articles.all() (reverse via related_name). ManyToManyField: class Article(models.Model): tags = models.ManyToManyField(Tag, blank=True, through="ArticleTag"). Through model (extra fields on the relationship): class ArticleTag(models.Model): article = models.ForeignKey(Article, on_delete=models.CASCADE) tag = models.ForeignKey(Tag, on_delete=models.CASCADE) created_by = models.ForeignKey(User, on_delete=models.CASCADE) added_at = models.DateTimeField(auto_now_add=True). Access: article.tags.add(tag); article.tags.remove(tag); article.tags.set([t1, t2]); article.tags.all(); tag.article_set.all(). OneToOneField: class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile"). Like ForeignKey but enforces uniqueness — only one Profile per User. Access: user.profile (direct, no _set). Self-referential: parent = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name="children"). Generic relations: use ContentType for polymorphic FK — point to any model. from django.contrib.contenttypes.fields import GenericForeignKey.

Open this question on its own page
04

What is Django Celery for background tasks?

Celery is the most popular Python task queue, used with Django for asynchronous/background task execution. Setup: pip install celery redis django-celery-results. Create celery.py in project root: from celery import Celery import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings") app = Celery("myproject") app.config_from_object("django.conf:settings", namespace="CELERY") app.autodiscover_tasks(). Settings: CELERY_BROKER_URL = "redis://localhost:6379/0" CELERY_RESULT_BACKEND = "django-db" # or redis:// CELERY_ACCEPT_CONTENT = ["json"] CELERY_TASK_SERIALIZER = "json". Defining tasks: from celery import shared_task @shared_task(bind=True, max_retries=3, default_retry_delay=60) def send_welcome_email(self, user_id): try: user = User.objects.get(id=user_id) send_email(user.email, "Welcome!", "welcome.html") except Exception as exc: raise self.retry(exc=exc). Calling tasks: send_welcome_email.delay(user.id) # Async, returns AsyncResult send_welcome_email.apply_async(args=[user.id], countdown=60) # Delay 60s send_welcome_email.apply_async(args=[user.id], eta=datetime(2024, 1, 15)). Periodic tasks (beat): CELERY_BEAT_SCHEDULE = {"send-daily-report": {"task": "myapp.tasks.daily_report", "schedule": crontab(hour=8, minute=0)}}. Run: celery -A myproject worker -l info (worker) and celery -A myproject beat -l info (scheduler). Monitoring: Flower — web UI for monitoring Celery workers and tasks.

Open this question on its own page
05

What is Django testing?

Django's testing framework extends Python's unittest with Django-specific tools: TestCase classes: from django.test import TestCase, Client, RequestFactory class ArticleViewTest(TestCase): def setUp(self): self.user = User.objects.create_user("alice", "alice@example.com", "pass123") self.client = Client() self.client.login(username="alice", password="pass123") self.article = Article.objects.create(title="Test", content="Content", author=self.user) def test_article_list(self): response = self.client.get("/articles/") self.assertEqual(response.status_code, 200) self.assertContains(response, "Test") self.assertTemplateUsed(response, "articles/list.html") def test_create_article(self): response = self.client.post("/articles/create/", {"title": "New", "content": "Body"}) self.assertEqual(response.status_code, 302) # redirect on success self.assertEqual(Article.objects.count(), 2) def test_unauthorized_delete(self): other_user = User.objects.create_user("bob", password="pass") self.client.login(username="bob", password="pass") response = self.client.delete(f"/articles/{self.article.pk}/delete/") self.assertEqual(response.status_code, 403). DRF testing: from rest_framework.test import APITestCase, APIClient class UserAPITest(APITestCase): def test_create_user(self): data = {"username": "alice", "email": "a@a.com", "password": "pass123"} response = self.client.post("/api/users/", data, format="json") self.assertEqual(response.status_code, 201). Factories: use factory_boy for test data: class ArticleFactory(factory.django.DjangoModelFactory): class Meta: model = Article title = factory.Sequence(lambda n: f"Article {n}"). Fixtures vs Factories: factories are preferred — more maintainable. python manage.py test --verbosity=2 --keepdb.

Open this question on its own page
06

What is Django security best practices?

Django has built-in security features and best practices for production: 1. HTTPS everywhere: SECURE_SSL_REDIRECT = True SECURE_HSTS_SECONDS = 31536000 SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True. 2. CSRF protection: CsrfViewMiddleware — always enabled. Use {% csrf_token %} in all POST forms. For AJAX: include CSRF token in headers. Exempt specific views: @csrf_exempt (use rarely). 3. XSS prevention: Django templates auto-escape HTML by default. Use |safe filter ONLY for trusted content. 4. SQL injection: Django ORM parameterizes queries — never use string formatting in queries: bad: query = f"SELECT * FROM users WHERE id = {user_id}"; good: User.objects.get(id=user_id). If using raw SQL: User.objects.raw("SELECT * FROM users WHERE id = %s", [user_id]). 5. Secret key: keep SECRET_KEY in environment variables, never in code. Rotate if exposed. 6. DEBUG = False in production: DEBUG exposes stack traces. 7. ALLOWED_HOSTS: prevents HTTP Host header attacks. 8. User input: validate all input — use forms with validators, serializers. 9. File uploads: validate file types/sizes. Store outside web root. Use whitelisted extensions. 10. Dependencies: keep Django and packages updated. Use pip-audit or Snyk. 11. Rate limiting: throttle authentication endpoints. Use fail2ban for brute force. 12. Clickjacking: X_FRAME_OPTIONS = "DENY". 13. Content Security Policy: use django-csp.

Open this question on its own page
07

What is Django Generic Views and Mixins?

Django's generic class-based views provide reusable base classes for common patterns, reducing boilerplate. Display views: class ArticleListView(ListView): model = Article template_name = "articles/list.html" context_object_name = "articles" paginate_by = 20 queryset = Article.objects.filter(is_published=True).select_related("author") ordering = ["-published_at"] def get_queryset(self): qs = super().get_queryset() category = self.request.GET.get("category") if category: qs = qs.filter(category__slug=category) return qs def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["categories"] = Category.objects.all() return context. Edit views: class ArticleCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): model = Article form_class = ArticleForm template_name = "articles/create.html" success_url = reverse_lazy("article-list") success_message = "Article created successfully!" def form_valid(self, form): form.instance.author = self.request.user return super().form_valid(form). Mixins for access control: LoginRequiredMixin — redirect to login if not authenticated; PermissionRequiredMixin — require specific permission; UserPassesTestMixin — custom test: def test_func(self): return self.request.user == self.get_object().author. Common mixins: SuccessMessageMixin, MultipleObjectMixin, SingleObjectMixin. Method resolution order (MRO): order of mixins matters — Django uses Python MRO for method resolution. Place LoginRequiredMixin before the view class.

Open this question on its own page
08

What is Django channels and WebSockets?

Django Channels extends Django to handle asynchronous protocols — primarily WebSockets, but also HTTP long-polling, MQTT, and more. It layers an async event loop on top of Django's synchronous core. Setup: pip install channels channels-redis daphne. Replace WSGI with ASGI: ASGI_APPLICATION = "myproject.asgi.application" CHANNEL_LAYERS = {"default": {"BACKEND": "channels_redis.core.RedisChannelLayer", "CONFIG": {"hosts": [("127.0.0.1", 6379)]}}}. Consumer (WebSocket handler): from channels.generic.websocket import AsyncWebsocketConsumer import json class ChatConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_name = self.scope["url_route"]["kwargs"]["room_name"] self.room_group_name = f"chat_{self.room_name}" await self.channel_layer.group_add(self.room_group_name, self.channel_name) await self.accept() async def disconnect(self, close_code): await self.channel_layer.group_discard(self.room_group_name, self.channel_name) async def receive(self, text_data): data = json.loads(text_data) await self.channel_layer.group_send(self.room_group_name, {"type": "chat.message", "message": data["message"]}) async def chat_message(self, event): await self.send(text_data=json.dumps({"message": event["message"]})). URL routing for WebSockets: from channels.routing import ProtocolTypeRouter, URLRouter websocket_urlpatterns = [path("ws/chat/<str:room_name>/", ChatConsumer.as_asgi())]. Run with Daphne: daphne myproject.asgi:application.

Open this question on its own page
09

What is Django model Meta options?

Django model Meta class configures model-level behavior: class Article(models.Model): title = models.CharField(max_length=200) published_at = models.DateTimeField() author = models.ForeignKey(User, on_delete=models.CASCADE) view_count = models.IntegerField(default=0) class Meta: # Database ordering default: ordering = ["-published_at"] # Verbose names for admin: verbose_name = "Article" verbose_name_plural = "Articles" # Database table name: db_table = "blog_articles" # Database indexes: indexes = [ models.Index(fields=["published_at", "is_published"]), models.Index(fields=["author", "-published_at"], name="author_date_idx") ] # Unique constraints: unique_together = [["author", "title"]] # or: constraints = [ models.UniqueConstraint(fields=["author", "title"], name="unique_author_title"), models.CheckConstraint(check=models.Q(view_count__gte=0), name="non_negative_views") ] # Permissions: permissions = [("publish_article", "Can publish articles"), ("feature_article", "Can feature articles")] # Abstract base model: abstract = True # Proxy model: proxy = True # App label (for installed apps): app_label = "blog" # Default manager: default_manager_name = "published". Abstract models: share fields across models without creating a separate table. All subclasses get all abstract model fields. Proxy models: create a Python-level subclass (different behavior/methods/ordering) without a separate database table.

Open this question on its own page
10

What is Django pagination?

Django's built-in Paginator class divides a queryset or list into pages: In views: from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger def article_list(request): queryset = Article.objects.filter(is_published=True) paginator = Paginator(queryset, per_page=10) page_number = request.GET.get("page", 1) try: page = paginator.page(page_number) except (PageNotAnInteger, EmptyPage): page = paginator.page(1) return render(request, "articles/list.html", {"page": page, "articles": page.object_list}). Template: {% for article in articles %}...{% endfor %} {% if page.has_previous %}<a href="?page={{ page.previous_page_number }}">Previous</a>{% endif %} Page {{ page.number }} of {{ page.paginator.num_pages }} {% if page.has_next %}<a href="?page={{ page.next_page_number }}">Next</a>{% endif %}. ListView pagination: just set paginate_by = 10 — automatic. Template variable: page_obj and paginator. DRF pagination: REST_FRAMEWORK = {"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", "PAGE_SIZE": 20}. Custom: class StandardPagination(PageNumberPagination): page_size = 20; page_size_query_param = "per_page"; max_page_size = 100. Response: {"count": 500, "next": "http://api.example.com/articles/?page=3", "previous": "...", "results": [...]}. Cursor pagination (DRF): for infinite scroll — more efficient than OFFSET for large datasets.

Open this question on its own page
11

What is Django custom manager and QuerySet?

Custom managers and QuerySets encapsulate reusable query logic in the model layer: Custom QuerySet: class ArticleQuerySet(models.QuerySet): def published(self): return self.filter(is_published=True) def by_author(self, user): return self.filter(author=user) def with_stats(self): return self.annotate(comment_count=Count("comments"), like_count=Count("likes")) def recent(self): return self.order_by("-published_at")[:10]. Custom Manager: class ArticleManager(models.Manager): def get_queryset(self): return ArticleQuerySet(self.model, using=self._db) def published(self): return self.get_queryset().published() def for_homepage(self): return self.published().with_stats().recent(). Apply to model: class Article(models.Model): ... objects = ArticleManager() # Replace default manager. Chaining (from_queryset): ArticleManager = models.Manager.from_queryset(ArticleQuerySet) class Article(models.Model): objects = ArticleManager(). Usage: Article.objects.published() Article.objects.published().by_author(user).with_stats() Article.objects.for_homepage(). Multiple managers: class Article(models.Model): objects = models.Manager() # Default all articles published = ArticleManager() # Published only. Use: Article.published.all(). First manager is default — affects admin and related lookups.

Open this question on its own page
12

What is Django content types framework?

Django's contenttypes framework enables generic relationships — a ForeignKey that can point to any model. Useful for: likes/reactions that work on any content type, activity feeds, comments on multiple models, tags. ContentType model: stores information about all installed models (app_label, model). from django.contrib.contenttypes.models import ContentType ct = ContentType.objects.get_for_model(Article) # or: ct = ContentType.objects.get(app_label="blog", model="article") model_class = ct.model_class() # returns Article class. Generic FK in model: from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation class Like(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey("content_type", "object_id") class Meta: unique_together = [["user", "content_type", "object_id"]] indexes = [models.Index(fields=["content_type", "object_id"])]. Reverse relations on the liked model: class Article(models.Model): ... likes = GenericRelation(Like, related_query_name="article"). Usage: Like.objects.create(user=user, content_object=article) article.likes.all() user_likes_article = Like.objects.filter(user=user, content_object=article).exists(). Prefetching generic relations: Article.objects.prefetch_related("likes"). Useful for building Instagram-style hearts or Reddit-style upvotes on multiple content types.

Open this question on its own page
Advanced 9 questions

Deep expertise questions for senior and lead roles.

01

What is Django's select_for_update and database locking?

select_for_update() executes a SELECT ... FOR UPDATE SQL statement, locking the selected rows until the transaction completes — preventing other transactions from modifying or locking the same rows. Essential for avoiding race conditions in concurrent operations. Usage: from django.db import transaction @transaction.atomic def process_payment(order_id, amount): # Lock the order row exclusively try: order = Order.objects.select_for_update().get(id=order_id) except Order.DoesNotExist: raise ValueError("Order not found") if order.status != "pending": raise ValueError("Order already processed") order.status = "processing" order.save() payment_result = payment_gateway.charge(amount) order.status = "paid" if payment_result.success else "failed" order.save() return order. Options: select_for_update(nowait=True) — raise OperationalError immediately instead of waiting if locked; select_for_update(skip_locked=True) — skip already-locked rows (good for job queue: multiple workers skip rows being processed); select_for_update(of=("self",)) — lock only specific tables in a JOIN; select_for_update(no_key=True) — PostgreSQL only, weaker lock allowing FK inserts. Must be inside a transaction: @transaction.atomic or with transaction.atomic():. Deadlock prevention: always acquire locks in consistent order across all transactions. Monitor deadlocks in pg_stat_activity. Alternative — optimistic locking: version field + conditional UPDATE: updated = Order.objects.filter(pk=id, version=old_version).update(status="paid", version=old_version+1). If updated == 0, conflict occurred — retry.

Open this question on its own page
02

What is Django's database optimization with query analysis?

Advanced Django query optimization techniques: 1. Django Debug Toolbar: shows all SQL queries per request with timing, duplicates. Essential for development: pip install django-debug-toolbar. 2. Query counting and timing: from django.db import connection, reset_queries from django.conf import settings settings.DEBUG = True reset_queries() # your view code print(len(connection.queries)) print(connection.queries) # list of SQL + execution time. 3. Explain query plan: qs = Article.objects.filter(is_published=True) print(qs.query) # Shows SQL qs.explain() # PostgreSQL EXPLAIN output. 4. only() and defer(): Article.objects.only("title", "published_at") # SELECT only these Article.objects.defer("content") # SELECT everything EXCEPT content. Only fetch what you need — especially avoid large text fields in list views. 5. values() and values_list(): Article.objects.values("title", "author__name") # dict list Article.objects.values_list("id", "title") # tuple list Article.objects.values_list("id", flat=True) # flat list of ids. Returns dicts/tuples not model instances — faster for read-only access. 6. bulk operations: Article.objects.bulk_create([Article(...), ...], batch_size=500) Article.objects.bulk_update(articles, ["title", "status"], batch_size=500) Article.objects.filter(...).update(is_published=True) Article.objects.filter(...).delete(). 7. aggregate vs annotate: aggregate returns a single value over QuerySet; annotate adds a computed value per row. 8. iterator(): for article in Article.objects.iterator(chunk_size=1000): — memory-efficient for processing large querysets without loading all into RAM.

Open this question on its own page
03

What is Django's transaction management in depth?

Django provides multiple levels of transaction management: Autocommit (default): each database operation is immediately committed. Atomic transactions: @transaction.atomic def transfer_funds(from_acc, to_acc, amount): # All or nothing from_acc.balance -= amount; from_acc.save() if from_acc.balance < 0: raise ValueError("Insufficient funds") # Rollback! to_acc.balance += amount; to_acc.save(). @transaction.atomic can be nested — inner decorators create savepoints. Context manager: with transaction.atomic(): order = Order.objects.create(...) with transaction.atomic(): # Savepoint try: process_payment(order) except PaymentError: # Rollback to savepoint, not entire transaction order.status = "payment_failed"; order.save(). Savepoints: from django.db import transaction sid = transaction.savepoint() try: ... except: transaction.savepoint_rollback(sid) else: transaction.savepoint_commit(sid). on_commit hooks: run code only after transaction successfully commits — ideal for side effects: @transaction.atomic def create_user(data): user = User.objects.create(**data) transaction.on_commit(lambda: send_welcome_email.delay(user.id)) # Task only runs if transaction commits. set_autocommit: transaction.set_autocommit(False) for manual control. Isolation levels: configure per database: DATABASES = {"default": {"OPTIONS": {"isolation_level": "repeatable read"}}}. TestCase vs TransactionTestCase: TestCase wraps each test in a transaction (fast); TransactionTestCase actually commits (required for testing on_commit hooks).

Open this question on its own page
04

What is Django's deployment best practices?

Production-ready Django deployment: WSGI/ASGI servers: never use Django's dev server in production. Use: Gunicorn (gunicorn myproject.wsgi:application -w 4 --timeout 120), uWSGI, Daphne (for async/WebSockets). Web server (reverse proxy): Nginx in front of Gunicorn: handles SSL termination, static/media files, load balancing, request buffering. Nginx config: location /static/ { alias /var/www/myapp/staticfiles/; expires 1y; add_header Cache-Control "public, immutable"; } location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }. Database: use PostgreSQL for production. Connection pooling: PgBouncer between Django and PostgreSQL. Set CONN_MAX_AGE in DATABASES for persistent connections: "CONN_MAX_AGE": 60. Static files: python manage.py collectstatic. Serve via Nginx or WhiteNoise. Use CDN for global distribution. Environment variables: use python-decouple or django-environ. Never commit secrets. Process management: Supervisor or systemd to keep Gunicorn running, auto-restart on crash, log management. Docker: Dockerfile with multi-stage build — builder installs dependencies, final image is minimal. CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "4"]. Health checks: /health/ endpoint returns 200 — used by load balancers and Kubernetes. Logging: structured JSON logging to stdout/stderr (no file logging in containers). Migrations: run python manage.py migrate as part of deployment, before starting new server.

Open this question on its own page
05

What is Django's caching strategies and cache invalidation?

Advanced Django caching strategies: Cache-Aside (Lazy Loading): most common pattern. Check cache → if miss, query DB, populate cache → return data: def get_user_dashboard(user_id): cache_key = f"user_dashboard_{user_id}_v2" data = cache.get(cache_key) if data is None: data = { "articles": list(Article.objects.filter(author_id=user_id).values()), "stats": UserStats.objects.get(user_id=user_id).__dict__ } cache.set(cache_key, data, timeout=300) return data. Write-Through: update cache when updating DB — always fresh but every write hits both: def update_article(pk, data): article = Article.objects.get(pk=pk) for k, v in data.items(): setattr(article, k, v) article.save() cache.set(f"article_{pk}", ArticleSerializer(article).data, 3600). Cache invalidation with signals: @receiver(post_save, sender=Article) def invalidate_article_cache(sender, instance, **kwargs): cache.delete(f"article_{instance.pk}") cache.delete(f"article_list_{instance.author_id}") cache.delete_pattern("article_list_*") # with django-redis. Versioned cache keys: def get_cache_key(model, pk): return f"{model.__name__}_{pk}_{settings.CACHE_VERSION}". Bump CACHE_VERSION to invalidate all caches at once. Cache warming: pre-populate cache after deploy with management command. Stampede prevention: cache lock (use django-redis cache.add() as atomic set-if-not-exists) or probabilistic early expiration. Distributed caching: Redis with sentinel or cluster for HA. Multiple Django instances share one Redis — critical for horizontal scaling.

Open this question on its own page
06

What is Django's performance with database connection pooling?

Advanced Django database performance and connection management: CONN_MAX_AGE: Django closes and reopens DB connections by default for each request. Set CONN_MAX_AGE for persistent connections: DATABASES = {"default": {"CONN_MAX_AGE": 60, "CONN_HEALTH_CHECKS": True}}. Each thread maintains a persistent connection for up to 60 seconds. Dramatically reduces connection overhead (PostgreSQL connection setup takes ~50-100ms). PgBouncer (connection pooler): between Django and PostgreSQL. Manages a pool of real DB connections shared across many app threads. Modes: session (one connection per client session), transaction (one connection per transaction — best), statement. Configure: DATABASE_URL = "postgresql://user:pass@pgbouncer:5432/mydb". django-db-geventpool: for async/gevent applications. Read replicas: route read queries to replicas, writes to primary. Use database router: class ReadWriteRouter: def db_for_read(self, model, **hints): return "replica" def db_for_write(self, model, **hints): return "primary" DATABASE_ROUTERS = ["myapp.routers.ReadWriteRouter"]. Queryset: Article.objects.using("replica").filter(...). Monitoring queries in production: enable log_min_duration_statement = 100 in PostgreSQL to log slow queries. Use pg_stat_statements to identify most time-consuming queries. Raw SQL for complex queries: Article.objects.raw("SELECT a.*, COUNT(c.id) as comment_count FROM articles a LEFT JOIN comments c ON c.article_id = a.id WHERE a.is_published = true GROUP BY a.id ORDER BY comment_count DESC LIMIT 10"). Indexed fields: add db_index=True or Meta.indexes on frequently filtered/sorted fields.

Open this question on its own page
07

What are Django custom template tags and filters?

Custom template tags and filters extend Django Template Language with project-specific functionality: File structure: myapp/templatetags/__init__.py myapp/templatetags/custom_tags.py. Load: {% load custom_tags %}. Simple filter: from django import template register = template.Library() @register.filter(name="multiply") def multiply(value, arg): return value * arg @register.filter def reading_time(content): words = len(content.split()) return max(1, words // 200) # minutes. Template: {{ article.price|multiply:1.2 }} {{ article.content|reading_time }} min read. Simple tag: @register.simple_tag def site_stats(): return {"articles": Article.objects.published().count(), "users": User.objects.active().count()}. Template: {% site_stats as stats %}{{ stats.articles }} articles. Inclusion tag (renders a template): @register.inclusion_tag("partials/user_card.html", takes_context=True) def user_card(context, user): return {"user": user, "request": context["request"], "is_own_profile": context["request"].user == user}. Template: {% user_card article.author %}. Block tag (full control): @register.tag def cache_block(parser, token): nodelist = parser.parse(("endcache_block",)) parser.delete_first_token() return CacheBlockNode(nodelist) class CacheBlockNode(template.Node): def render(self, context): # implement caching logic pass. Custom tags encapsulate complex logic, keeping templates clean.

Open this question on its own page
08

What is Django REST Framework ViewSets and Routers in depth?

DRF ViewSets and Routers provide the highest level of abstraction for REST APIs: ViewSet types: ViewSet — no default actions; GenericViewSet — provides get_queryset, get_serializer; ReadOnlyModelViewSet — list + retrieve; ModelViewSet — all CRUD actions. Custom actions with @action: class ArticleViewSet(viewsets.ModelViewSet): queryset = Article.objects.all() serializer_class = ArticleSerializer @action(detail=True, methods=["post"], permission_classes=[IsAuthenticated]) def publish(self, request, pk=None): article = self.get_object() if article.author != request.user: return Response({"error": "Not your article"}, status=403) article.is_published = True article.published_at = timezone.now() article.save() return Response(ArticleSerializer(article).data) @action(detail=False, methods=["get"], url_path="trending") def trending(self, request): qs = self.get_queryset().annotate(likes=Count("like")).order_by("-likes")[:10] return Response(ArticleSerializer(qs, many=True, context={"request": request}).data) @action(detail=True, methods=["get", "post"], url_path="comments") def comments(self, request, pk=None): article = self.get_object() if request.method == "GET": comments = article.comments.filter(is_approved=True) return Response(CommentSerializer(comments, many=True).data) serializer = CommentSerializer(data=request.data) if serializer.is_valid(): serializer.save(author=request.user, article=article) return Response(serializer.data, status=201) return Response(serializer.errors, status=400). Router generates URLs: GET/POST /articles/, GET/PUT/PATCH/DELETE /articles/{pk}/, POST /articles/{pk}/publish/, GET /articles/trending/, GET/POST /articles/{pk}/comments/. Nested routers: pip install drf-nested-routers for /articles/{pk}/comments/ nested routing.

Open this question on its own page
09

What is Django's asynchronous views (ASGI)?

Django 3.1+ supports async views via ASGI, allowing non-blocking I/O operations without blocking the server thread. Async view: import asyncio import aiohttp from django.http import JsonResponse async def aggregate_data(request): async with aiohttp.ClientSession() as session: tasks = [ session.get("https://api1.example.com/data"), session.get("https://api2.example.com/data"), session.get("https://api3.example.com/stats"), ] responses = await asyncio.gather(*tasks) results = [await r.json() for r in responses] return JsonResponse({"data": results}). Async ORM (Django 4.1+): async def user_list(request): users = [u async for u in User.objects.filter(is_active=True)[:100]] # or: users = await User.objects.filter(is_active=True).values_list("id", "username") return JsonResponse({"users": list(users)}). Async ORM methods: await obj.asave(), await obj.adelete(), await Model.objects.aget(pk=1), await Model.objects.acreate(...), await qs.acount(), await qs.aexists(), await qs.afirst(), async for item in qs:. sync_to_async: wrap synchronous code for use in async context: from asgiref.sync import sync_to_async get_user = sync_to_async(lambda pk: User.objects.get(pk=pk)). async_to_sync: call async code from sync context: from asgiref.sync import async_to_sync result = async_to_sync(async_function)(). Running with ASGI: uvicorn myproject.asgi:application --workers 4 or Daphne. Async views only help for I/O-bound work. CPU-bound: use Celery workers.

Open this question on its own page
Back to All Topics 42 questions total