Typorithm · easy

A Django project and its settings boundary

pythondjangoindependent-practice
Saved on this device
Full lesson · 4 learning steps Open any exercise for focused practice
1

Step 1 of 4 · intro card

A Django project and its settings boundary

0%

Concept and contract

Separate the project configuration, reusable app and request boundary before adding database behavior.

A Django project supplies configuration and entry points, while apps group related models, views and other behavior. Start with that distinction rather than putting every operation in one settings file.

Our companion helper configures a named test app and an in-memory database only. It is fixture setup, not a production settings template. A real project normally starts with startproject and an explicit settings module selected by its deployment.

Mechanism and worked example

The worked view calls request.get_host, so the configured ALLOWED_HOSTS rule is actually exercised.

The worked view calls request.get_host, so the configured ALLOWED_HOSTS rule is actually exercised. The test client supplies one controlled Host header, and DEBUG stays false.

An accepted host produces a JSON response; an unapproved host becomes a handled bad request. override_settings restores the previous settings after the call, allowing cases to run without permanently changing another part of the test process.

Complete worked example

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.http import JsonResponse
from django.test import Client, override_settings
from django.urls import path

def health(request):
    return JsonResponse({"host": request.get_host()})

urlpatterns = [path("health/", health)]

def inspect_host(host):
    with override_settings(DEBUG=False, ALLOWED_HOSTS=["testserver"]):
        return Client().get("/health/", HTTP_HOST=host).status_code
Reasoning
The worked view calls request.get_host, so the configured ALLOWED_HOSTS rule is actually exercised. The test client supplies one controlled Host header, and DEBUG stays false.

Counterexamples and common mistakes

The counterexample allows every host with an asterisk.

The counterexample allows every host with an asterisk. It makes the fixture look convenient while removing the boundary the lesson claims to enforce.

ALLOWED_HOSTS is not a login system, a CORS policy or a substitute for trusted proxy configuration. Do not copy the publicly visible fixture secret into a deployed project. Keep real secrets outside source control and inspect the configuration used by the actual serving process.

Counterexample: a runnable framework mistake

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.http import JsonResponse
from django.test import Client, override_settings
from django.urls import path

def health(request):
    return JsonResponse({"host": request.get_host()})

urlpatterns = [path("health/", health)]

def inspect_host(host):
    with override_settings(DEBUG=False, ALLOWED_HOSTS=["*"]):
        return Client().get("/health/", HTTP_HOST=host).status_code
Reasoning
The counterexample allows every host with an asterisk. It makes the fixture look convenient while removing the boundary the lesson claims to enforce.

Independent practice: one bounded framework change

Allow preview.test as one additional explicit host while keeping unrelated hosts rejected.

Allow preview.test as one additional explicit host while keeping unrelated hosts rejected. Begin with the original host, add the preview hostname and then verify that an unlisted hostname still receives a bad-request response.

This is a small allowlist modification, not an exercise in creating a wildcard development configuration. Keep the override local so the following lesson cases do not inherit your changed settings.

Step 1: Add preview.test to the explicit host allowlist. Step 2: Keep unknown hosts rejected and DEBUG disabled.

Practice starter: solve before reading the solution

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.http import JsonResponse
from django.test import Client, override_settings
from django.urls import path

def health(request):
    return JsonResponse({"host": request.get_host()})

urlpatterns = [path("health/", health)]

def inspect_host(host):
    # Remove this placeholder, then adapt the retained baseline:
    # Add preview.test to the explicit host allowlist.
    raise NotImplementedError
    with override_settings(DEBUG=False, ALLOWED_HOSTS=["testserver"]):
        return Client().get("/health/", HTTP_HOST=host).status_code
Reasoning
Add preview.test to the explicit host allowlist. Keep unknown hosts rejected and DEBUG disabled.
  • Hint 1: Change the list inside override_settings only.
  • Hint 2: Check the unapproved hostname after adding the valid preview host.

Solution, tests and trade-offs

The cases test ordinary hosts and a host containing an explicit port, demonstrating that host validation is more precise than comparing an entire raw header string.

The cases test ordinary hosts and a host containing an explicit port, demonstrating that host validation is more precise than comparing an entire raw header string. The practice adds a second allowed hostname and preserves the rejected case.

These checks use Django’s real request handling rather than a separate hand-written validator. They do not start a public server, change DNS or establish a complete deployment security review.

Practice solution and acceptance checks

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.http import JsonResponse
from django.test import Client, override_settings
from django.urls import path

def health(request):
    return JsonResponse({"host": request.get_host()})

urlpatterns = [path("health/", health)]

def inspect_host(host):
    with override_settings(DEBUG=False, ALLOWED_HOSTS=["testserver", "preview.test"]):
        return Client().get("/health/", HTTP_HOST=host).status_code
Reasoning
The cases test ordinary hosts and a host containing an explicit port, demonstrating that host validation is more precise than comparing an entire raw header string. The practice adds a second allowed hostname and preserves the rejected case.

Interview reasoning and next step

Explain the route from a settings module through middleware to a view.

Explain the route from a settings module through middleware to a view. Then identify which configuration belongs to one environment and which app code should remain reusable.

Django 6.1 is the pinned teaching version; use its documentation instead of assuming every older tutorial has the same APIs. The next lesson adds named routes so callers can generate paths from route identity instead of copying string literals everywhere.

Optional stretch — after the core task works: Run Django deployment checks against a separate synthetic production configuration.

Computer practice: https://applydjinn.com/typorithm/python-frameworks-lab-20261105.zip. Install the pinned dependencies in an isolated environment, run verify.py --track django, then edit the retained exercise baseline and check it with --practice dj-project. The lab uses owned in-memory databases, local framework clients and tiny CPU tensors. It never reads the working ApplyDjinn database, contacts production feeds or downloads models.

Separate the project configuration, reusable app and request boundary before adding database behavior.