In Django, what is the difference between a project and an app, and what do startproject and startapp each create?
answer
- one settings module versus many packages
- configuration versus features
- wired in through INSTALLED_APPS
- manage.py, settings, urls, wsgi, asgi
basics
~20 sA 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 sThe **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
Define project as the configured site and app as a feature package, and list what startproject and startapp generate.
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.
Judge when code deserves its own app versus a module inside an existing one, keeping models, migrations and admin cohesive per app.
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