skip to content

In Django, what is the difference between a project and an app, and what do startproject and startapp each create?

level: juniorimportance: must knowfreq 70%

answer

  1. one settings module versus many packages
  2. configuration versus features
  3. wired in through INSTALLED_APPS
  4. manage.py, settings, urls, wsgi, asgi

basics

~20 s

A Django project is the configured site: a settings module, a root URLconf and the WSGI/ASGI entry points. An app is a Python package providing one set of features, enabled by listing it in INSTALLED_APPS; one project combines many apps.

solid answer

~40 s

The **project** is the whole configured web application. `django-admin startproject clinic` creates `manage.py` and a `clinic` package with `settings.py`, `urls.py`, `asgi.py` and `wsgi.py`. An **app** is a Python package that provides one set of features — models, views, templates, static files, admin registrations. `python manage.py startapp scheduling` creates `__init__.py`, `admin.py`, `apps.py`, `migrations/`, `models.py`, `tests.py` and `views.py`. An app does nothing until the project lists it in `INSTALLED_APPS` and, for URLs, includes its URLconf. A project holds many apps, an app can be installed in many projects, and Django's docs note there is no `Application` object: the registry keeps an `AppConfig` per installed app.

go deeper

for a junior

Define project as the configured site and app as a feature package, and list what startproject and startapp generate.

for a middle

Explain that INSTALLED_APPS turns a package into an app, that the registry keeps one AppConfig per app, and that apps share one process and settings.

for a senior

Judge when code deserves its own app versus a module inside an existing one, keeping models, migrations and admin cohesive per app.

for a principal

Frame apps as the unit of ownership and reuse across teams, and weigh the migration cost of getting boundaries wrong early.

## Two different units Django separates **configuration** from **features**. The **project** is the configured site; an **app** is a reusable bundle of features the project switches on. Getting this split right is the first design decision on any Django codebase, including a clinic-booking system with scheduling, patients and billing. ## What the project is Django's documentation says a project "is defined primarily by a settings module". Running `django-admin startproject clinic` produces: - `manage.py` — a thin wrapper that sets `DJANGO_SETTINGS_MODULE` and runs management commands; - `clinic/settings.py` — `INSTALLED_APPS`, `MIDDLEWARE`, `DATABASES`, `TEMPLATES` and the rest; - `clinic/urls.py` — the root URLconf that `ROOT_URLCONF` points at; - `clinic/wsgi.py` and `clinic/asgi.py` — the entry points servers import; - `clinic/__init__.py` — making it a package. The project package can also hold site-wide templates, fixtures or static files that belong to no single app. ## What an app is An **app** is "a Python package that provides some set of features". Running `python manage.py startapp scheduling` produces: | File | Purpose | |---|---| | `__init__.py` | makes the directory a package | | `apps.py` | an `AppConfig` subclass with `name = 'scheduling'` | | `models.py` | the app's models | | `migrations/` | the app's migration files | | `admin.py` | admin registrations | | `views.py` | the app's views | | `tests.py` | the app's tests | There is no `urls.py` in the generated app; you add one when the app serves URLs. Since Django 6.0 the generated `apps.py` no longer sets `default_auto_field`, because `DEFAULT_AUTO_FIELD` itself now defaults to `BigAutoField`. ## How the two connect 1. **`INSTALLED_APPS`** lists the app, either as a package path (`"scheduling"`) or as the dotted path to its config class (`"scheduling.apps.SchedulingConfig"`, which the settings reference calls preferred). 2. The **app registry** (`django.apps.apps`) creates one `AppConfig` per entry at startup, imports each app's models and then runs each `ready()`. 3. The root **URLconf** includes the app's URL patterns, if it has any. 4. Other mechanisms — `MIDDLEWARE`, template inheritance — can also pull app code in. The docs stress there is no `Application` object at runtime: an app is "a set of code that interacts with various parts of the framework", and `AppConfig` is only its metadata record. ## Common confusions - **"An app is a microservice."** No — all apps in a project share one process, one settings module and usually one database. - **"Every folder in the project is an app."** Only packages listed in `INSTALLED_APPS` are apps to Django; a `utils/` package is just Python. - **"The project package cannot have models."** It can, if you add it to `INSTALLED_APPS`, though keeping models in apps is the norm. - **"startapp registers the app."** It only creates files; the app is inactive until you add it to `INSTALLED_APPS`. ## A worked split for a clinic-booking site A clinic-booking project might look like this after the first week: ```text clinic/ # project root, contains manage.py manage.py clinic/ # project package: settings, root URLconf, entry points settings.py urls.py asgi.py wsgi.py accounts/ # app: custom user model patients/ # app: patient records scheduling/ # app: slots and appointments billing/ # app: invoices and payments ``` Each of `accounts`, `patients`, `scheduling` and `billing` is listed in `INSTALLED_APPS`, owns its own `migrations/` directory, and contributes URLs through an `include()` in `clinic/urls.py`. The `clinic` package itself stays small: configuration and wiring, not features. When a second clinic product later needs appointment scheduling, the `scheduling` app is the unit that could be extracted, which is exactly what the project/app split is for. ## What an interviewer is listening for A junior answer distinguishes the configured site from the feature packages and knows the files each command creates. A stronger answer explains that `INSTALLED_APPS` is what turns a package into an app, and that apps are the unit of reuse — which is why third-party packages such as Django's own `django.contrib.admin` are apps too.

  • What is the difference between django-admin startproject and python manage.py startapp?
    `startproject` runs before any project exists, so it is a `django-admin` command that creates `manage.py` and the settings package. `startapp` is usually run through `manage.py`, which already knows the settings module; it creates a new app package inside the project root. Neither command edits `INSTALLED_APPS` for you.
  • Can a project run with an app that has no models?
    Yes. An app is any package that provides features: it might contribute only template tags, management commands, static files or middleware. Listing it in `INSTALLED_APPS` is still what makes Django look for those resources in it, such as its `templates/` directory or its `management/commands/` modules.

A project is a clinic building with its wiring and front desk; apps are the departments. A department does nothing until the building lists it in the directory and gives it a door, which is what INSTALLED_APPS and the URLconf do.

saying these in an interview costs you the question

  • Calls each Django app a separate service with its own process
  • Believes startapp adds the app to INSTALLED_APPS automatically
  • Says a project can contain only one app
  • Treats any Python package in the repository as a Django app
  • Thinks the project package can never define models