Django
Middleware, the ORM, signals, DRF, and Django auth.
14 questions
JuniorTheoryVery commonWhat is the Django ORM?
What is the Django ORM?
An object-relational mapper: you define tables as models.Model classes and query them in Python with .objects.filter(...) instead of raw SQL. It generates the SQL, manages migrations, and maps rows back to model instances.
Common mistakes
- ✗Thinking the ORM is its own database rather than a layer over one
- ✗Believing you must still hand-write all SQL yourself
- ✗Forgetting the ORM handles migrations as part of its job
Follow-up questions
- →How do
QuerySets lazily defer the actual SQL execution? - →When would you drop to
raw()or.extra()SQL?
MiddleTheoryVery commonHow does Django's authentication system work?
How does Django's authentication system work?
It ships users, groups, permissions, and cookie sessions. AuthenticationMiddleware attaches request.user per request; authentication verifies identity by login/password with hashers, authorization checks permissions. OAuth is third-party.
Common mistakes
- ✗Believing Django stores passwords in plain text rather than hashed
- ✗Thinking there are no built-in groups or permissions
- ✗Assuming the view, not
AuthenticationMiddleware, setsrequest.user
Follow-up questions
- →How does a pluggable password hasher upgrade old hashes on login?
- →What is the difference between authentication and authorization here?
JuniorTheoryCommonWhat is the inner Meta class in a Django model or serializer?
What is the inner Meta class in a Django model or serializer?
A nested configuration class holding metadata about the outer class — like model, fields/exclude, ordering, and db table name — read by Django's metaclass when the class is built. It configures the class; it is not itself a field.
Common mistakes
- ✗Declaring data fields inside
Metainstead of on the class body - ✗Treating
Metaas a base class you inherit rather than nested config - ✗Assuming every plain Python class needs a
Meta
Follow-up questions
- →Name three options you can set on a model's
Meta. - →How does
ModelSerializeruse its innerMeta?
JuniorTheoryCommonWhat is middleware in Django?
What is middleware in Django?
A pluggable hook that wraps every request and response. You enable it by adding its path to MIDDLEWARE; entries run top-down on the request and bottom-up on the response, and any one can inspect, modify, or short-circuit with its own reply.
Common mistakes
- ✗Thinking middleware sees only the request and cannot touch the response
- ✗Forgetting that order in
MIDDLEWAREmatters — request top-down, response bottom-up - ✗Believing middleware applies to a single view rather than every request
Follow-up questions
- →What is the difference between
process_requestandprocess_responseordering? - →How would you short-circuit a request before it reaches the view?
MiddleCodeCommonRefactor two Django models duplicating amount fields and to_dict
Refactor two Django models duplicating amount fields and to_dict
Pull the shared amount_* fields and to_dict into an abstract base model — class AmountBase(models.Model): ... with class Meta: abstract = True — and have both models inherit it; abstract bases create no table, only inherited columns. The key correctness fix: money as FloatField is a bug (binary float rounding) — use DecimalField. Also reconsider the loose null=True on amount/currency fields.
Common mistakes
- ✗Using concrete inheritance instead of an abstract base
- ✗Keeping
FloatFieldfor money instead ofDecimalField - ✗Forgetting
class Meta: abstract = Trueso a spurious table is created
Follow-up questions
- →Why is
FloatFieldwrong for money andDecimalFieldright? - →How does an abstract base model differ from multi-table inheritance?
MiddleTheoryCommonHow does Django's CSRF middleware protect POST requests?
How does Django's CSRF middleware protect POST requests?
CsrfViewMiddleware puts a random token in a cookie and makes unsafe methods (POST/PUT/DELETE) echo a matching csrfmiddlewaretoken in a form field or header; a mismatch returns 403. GET is exempt, and @csrf_exempt opts a view out.
Common mistakes
- ✗Thinking the CSRF token is secret like a password rather than a per-request nonce
- ✗Believing GET requests are validated for a CSRF token
- ✗Slapping
@csrf_exempton a view to silence a 403 without understanding it
Follow-up questions
- →Why are GET and HEAD requests exempt from the CSRF check?
- →How do you send the CSRF token from a JavaScript fetch call?
MiddleTheoryCommonHow is a many-to-many relation stored at the database level?
How is a many-to-many relation stored at the database level?
As a separate join (bridge) table holding foreign keys to both sides plus any extra fields, since one column can't reference many rows. Queries JOIN through it, and Django auto-creates this table for a ManyToManyField.
Common mistakes
- ✗Imagining m2m as a comma-separated list in one column
- ✗Forgetting the relation needs its own join table
- ✗Not knowing you add fields to m2m via a
throughmodel
Follow-up questions
- →When do you need an explicit
throughmodel on aManyToManyField? - →How does
JOINing through the bridge table avoid duplicate rows?
MiddleTheoryCommonHow do select_related and prefetch_related differ in Django?
How do select_related and prefetch_related differ in Django?
select_related performs a SQL JOIN and pulls the related rows in one query — only for single-valued relations (ForeignKey, one-to-one). prefetch_related runs a separate query per relation and joins them in Python — it supports many-to-many and reverse ForeignKey. Both fix the N+1 query problem by loading related objects up front instead of per access.
Common mistakes
- ✗Swapping which method does the SQL
JOINversus per-relation query - ✗Using
select_relatedon a many-to-many relation - ✗Not realizing both methods exist to solve the N+1 problem
Follow-up questions
- →What is the N+1 query problem these methods address?
- →When would
prefetch_relatedissue more queries than expected?
MiddleTheoryCommonWhat does a Django REST Framework serializer do?
What does a Django REST Framework serializer do?
It converts between model instances and primitive types like JSON: serializing data out for API responses, and validating then deserializing incoming data into instances. A ModelSerializer derives its fields from a model via its Meta.
Common mistakes
- ✗Thinking serializers only format output and skip input validation
- ✗Believing a serializer queries the DB directly instead of via the model
- ✗Forgetting
ModelSerializerreads its fields from the innerMeta
Follow-up questions
- →How does
is_valid()relate tovalidated_dataandsave()? - →When would you write a plain
Serializerinstead ofModelSerializer?
JuniorTheoryOccasionalWhat are Django signals?
What are Django signals?
A publish/subscribe mechanism: components emit signals like pre_save and post_save, and registered receivers react. Dispatch is SYNCHRONOUS — it runs inside the same request, so a slow receiver directly slows the response that fired it.
Common mistakes
- ✗Assuming signals run asynchronously in the background rather than synchronously
- ✗Expecting
post_saveto fire on bulkqueryset.update()or.delete() - ✗Overusing signals where an explicit method call would be clearer
Follow-up questions
- →Why might overusing signals make code harder to follow?
- →How do you make a signal receiver fire only once per process?
JuniorTheoryOccasionalHow do Django and Flask differ in philosophy?
How do Django and Flask differ in philosophy?
Django is batteries-included: a built-in ORM, admin, auth, templating, and project structure ship full sites fast. Flask is a microframework with a minimal core — you pick each component yourself, keeping it flexible for small services.
Common mistakes
- ✗Believing Flask ships a built-in ORM and admin like Django does
- ✗Thinking Django cannot be customized or have components swapped
- ✗Treating one as strictly better instead of fit-for-purpose
Follow-up questions
- →When would you reach for Flask over Django on a new project?
- →What does
django-admin startprojectscaffold that Flask leaves to you?
MiddleCodeOccasionalOrder a Django queryset by an arbitrary in-memory id list
Order a Django queryset by an arbitrary in-memory id list
Annotate each row with its position in the list using Case/When, then order by that annotation: preserved = Case(*[When(id=pk, then=pos) for pos, pk in enumerate(ids)]), then MyModel.objects.filter(pk__in=ids).annotate(_order=preserved).order_by('_order'). The database evaluates the CASE expression per row, so the requested order is produced in SQL, not re-sorted in Python.
Common mistakes
- ✗Assuming
pk__inpreserves the order of the id list - ✗Re-sorting in Python instead of letting SQL do it
- ✗Ordering by
idand assuming it matches the custom order
Follow-up questions
- →Why does
pk__innot guarantee the order of its argument list? - →How does the
CASEexpression map each id to its position?
SeniorTheoryOccasionalWhy does Django's CSRF check exempt GET and add a referer check on HTTPS?
Why does Django's CSRF check exempt GET and add a referer check on HTTPS?
Safe methods (GET/HEAD/OPTIONS/TRACE) must be side-effect-free per HTTP, so a forged GET can't cause harm and is exempt. Over HTTPS Django also checks Referer/Origin against trusted hosts to block MITM cookie-injection.
Common mistakes
- ✗Assuming GET is exempt for speed rather than its side-effect-free semantics
- ✗Thinking the referer/origin check runs on plain HTTP too
- ✗Believing the CSRF token is stored server-side in the session by default
Follow-up questions
- →How does the
Originheader strengthen theReferer-based check? - →Why can a session-independent token still be defeated by MITM on HTTP?
MiddleDesignRareA CurrencyRate model stores rate and datetime rows (e.g. 34.9 at 1999-05-21, 70.3 at 2022-12-20). Design a Django view that, given a requested datetime, returns the rate whose stored datetime is closest to it — closest may be before or after the request (2022-12-19 returns 70.3; 2000-05-21 returns 34.9). Explain the query strategy, why a naive single-direction lookup is wrong, and how you would keep it efficient on a large table.
A CurrencyRate model stores rate and datetime rows (e.g. 34.9 at 1999-05-21, 70.3 at 2022-12-20). Design a Django view that, given a requested datetime, returns the rate whose stored datetime is closest to it — closest may be before or after the request (2022-12-19 returns 70.3; 2000-05-21 returns 34.9). Explain the query strategy, why a naive single-direction lookup is wrong, and how you would keep it efficient on a large table.
Query both neighbours: the nearest row at or after the requested time (filter(datetime__gte=t).order_by('datetime').first()) and the nearest at or before it (filter(datetime__lte=t).order_by('-datetime').first()), then return whichever has the smaller absolute time delta. A naive one-sided .first() ignores the closer row on the other side. With an index on datetime, each bounded query is an index seek — efficient even on a large table.
Common mistakes
- ✗Checking only one direction and missing the closer neighbour
- ✗Loading all rows into Python instead of letting the database bound the search
- ✗Forgetting to index
datetime, making each lookup a full scan
Follow-up questions
- →How would you solve this in one SQL query instead of two?
- →What index would you add, and why does it bound each query?