Projects vs Apps

Reviewed & published by Brayan K

In Django, a project is the overall configuration and container for a website, while an app is a self-contained, reusable module inside that project that handles one specific feature (like a blog, a poll, or user accounts).

Part of the free Django course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

In this lesson you'll learn exactly how projects and apps differ, how to create an app, what files Django generates for you, and the one step beginners always forget — registering the app so Django actually uses it.

What You'll Learn in This Lesson

1 Project vs App: The Conceptual Difference

A project is the whole website. It owns the global configuration in settings.py, the root URL routing table in urls.py, and the server entry points (wsgi.py and asgi.py). There is exactly one project per site.

An app is a self-contained module that delivers one feature — a blog, a poll, user accounts, a shopping cart. A project can contain many apps, and a single well-built app can be dropped into a completely different project and reused.

Here is how the two folder structures relate inside a single site:

mysite/                  # ← the PROJECT (the whole website)
    manage.py
    mysite/              # project configuration package
        __init__.py
        settings.py      # INSTALLED_APPS lives here
        urls.py          # root URL routing
        wsgi.py
        asgi.py
    blog/                # ← an APP (one feature: a blog)
        models.py
        views.py
        ...
    accounts/            # ← another APP (user accounts)
        models.py
        views.py
        ...
# A quick mental model in plain Python: a project "contains" apps.
# Each app is responsible for exactly one feature.

class App:
    def __init__(self, name, feature):
        self.name = name
        self.feature = feature

class Project:
    def __init__(self, name):
        self.name = name
        self.apps = []

    def add_app(self, app):
        self.apps.append(app)

mysite = Project("mysite")
mysite.add_app(App("blog", "publish articles"))
mysite.add_app(App("accounts", "user login and signup"))
mysite.add_app(App("polls", "run surveys"))

print(f"Project '{mysite.name}' contains {len(mysite.apps)} apps:")
for app in mysite.apps:
    print(f"  - {app.name}: {app.feature}")

# A project is the container; each app handles one focused feature.

# ✅ Expected output:
# Project 'mysite' contains 3 apps:
#   - blog: publish articles
#   - accounts: user login and signup
#   - polls: run surveys

2 Creating an App with startapp

From inside your project folder (the one containing manage.py), run the startapp command. Here we create an app named blog:

# Run this from the folder that contains manage.py
python manage.py startapp blog

Django generates a new blog/ folder with these files:

blog/
    __init__.py          # marks the folder as a Python package
    apps.py              # app configuration class (BlogConfig)
    models.py            # your database models go here
    views.py             # request-handling functions/classes
    admin.py             # register models with the admin site
    tests.py             # write tests for this app
    migrations/
        __init__.py      # holds generated migration files
# startapp creates several files. Here's the essence of what goes in each
# one — shown as real Django code so you recognise it later.

# apps.py — names and configures the app
class BlogConfig:
    default_auto_field = "django.db.models.BigAutoField"
    name = "blog"

# models.py — describes your data (a database table)
# from django.db import models
class Post:
    # title = models.CharField(max_length=200)
    # body = models.TextField()
    pass

# views.py — handles a request and returns a response
def post_list(request):
    return "A page listing every blog post"

# Simulate Django wiring them together:
config = BlogConfig()
print("App name:", config.name)
print("Auto field:", config.default_auto_field)
print("View output:", post_list({"path": "/blog/"}))

# ✅ Expected output:
# App name: blog
# Auto field: django.db.models.BigAutoField
# View output: A page listing every blog post

3 Registering the App in INSTALLED_APPS

Creating the app folder is only half the job. Django does not know the app exists until you add it to the INSTALLED_APPS list in settings.py. This single step is the one beginners forget most often.

# mysite/settings.py

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "blog",          # ← your new app, registered here
    # or the fully-qualified config: "blog.apps.BlogConfig"
]

Once registered, Django will:

# INSTALLED_APPS is just a Python list. Registering an app is literally
# appending its name so Django can "see" it.

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.staticfiles",
]

def register_app(app_name):
    if app_name in INSTALLED_APPS:
        print(f"'{app_name}' is already registered.")
    else:
        INSTALLED_APPS.append(app_name)
        print(f"Registered '{app_name}' — Django can now see it.")

register_app("blog")
register_app("accounts")
register_app("blog")   # already there

print("\nFinal INSTALLED_APPS:")
for app in INSTALLED_APPS:
    print("  -", app)

# ✅ Expected output:
# Registered 'blog' — Django can now see it.
# Registered 'accounts' — Django can now see it.
# 'blog' is already registered.
#
# Final INSTALLED_APPS:
#   - django.contrib.admin
#   - django.contrib.auth
#   - django.contrib.staticfiles
#   - blog
#   - accounts

🎯 Your Turn: Register the Right App

Fill in the blank so the new app named polls is added to INSTALLED_APPS.

# 🎯 YOUR TURN: replace ___ with the app name "polls"

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "___",          # ← add the new app here
]

print("Registered apps:")
for app in INSTALLED_APPS:
    print("  -", app)

# EXPECTED OUTPUT (last line):
#   - polls

Common Errors (And How to Fix Them)

❌ My models don't appear / no migrations are created

You ran startapp but forgot to register the app, so Django never sees its models.

✅ Fix: add the app's name to INSTALLED_APPS in settings.py, then run makemigrations.

❌ CommandError: 'blog' conflicts with the name of an existing directory

An app (or folder) called blog already exists, so startapp refuses to overwrite it.

✅ Fix: choose a different app name, or delete/rename the existing folder if it was a mistake.

❌ can't open file 'manage.py': No such file or directory

You ran startapp from the wrong directory — manage.py isn't there.

✅ Fix: cd into the project folder that contains manage.py first, then run the command.

📋 Quick Reference

Term / CommandWhat It Means
django-admin startproject mysiteCreate the project (the whole site)
python manage.py startapp blogCreate an app (one feature) inside the project
INSTALLED_APPSList in settings.py where you register each app
models.pyDefines an app's database tables
apps.pyConfiguration class that names the app

🏆 Mini Challenge: Scaffold a Multi-App Project

Write a helper that prints the commands and the INSTALLED_APPS entries needed to add several apps to a project.

# 🏆 Mini Challenge: scaffold multiple apps and register them.

def scaffold(apps):
    print("# 1. Create each app:")
    for app in apps:
        print(f"python manage.py startapp {app}")

    print("\n# 2. Register them in settings.py:")
    print("INSTALLED_APPS = [")
    print("    # ...Django's built-in apps...")
    for app in apps:
        print(f'    "{app}",')
    print("]")

scaffold(["blog", "accounts", "polls"])

# EXPECTED: three startapp commands, then an INSTALLED_APPS list
# containing "blog", "accounts", and "polls".

❓ Frequently Asked Questions

Lesson complete — you can structure a Django site!

You now know that a project is the configuration and container while apps are focused, reusable feature modules. You can create an app with startapp, recognise every file it generates, and register the app in INSTALLED_APPS so Django actually uses it.

Practice quiz

In Django, what is a project?

  • A single reusable feature module
  • The overall website: configuration and container
  • A database table
  • A URL pattern

Answer: The overall website: configuration and container. A project is the whole site, holding settings.py, the root urls.py, and the server entry points.

What is a Django app?

  • A self-contained module for one feature
  • The global settings file
  • The web server
  • The database engine

Answer: A self-contained module for one feature. An app is a self-contained module that implements one specific feature and can be reused.

Which command creates a new app inside a project?

  • django-admin startproject
  • python manage.py runserver
  • python manage.py startapp
  • python manage.py migrate

Answer: python manage.py startapp. python manage.py startapp <name> scaffolds a new app folder.

Which command creates the project itself?

  • python manage.py startapp
  • python manage.py createproject
  • django-admin newsite
  • django-admin startproject

Answer: django-admin startproject. django-admin startproject <name> creates the project and its configuration package.

Which list must you add an app to so Django uses it?

  • INSTALLED_APPS
  • MIDDLEWARE
  • TEMPLATES
  • DATABASES

Answer: INSTALLED_APPS. An app must be registered in INSTALLED_APPS in settings.py before Django detects it.

What is the relationship between projects and apps?

  • One app contains many projects
  • One project can contain many apps
  • They are the same thing
  • Each app needs its own project

Answer: One project can contain many apps. A single project can contain many apps, and one app can be reused across projects.

Which file does startapp generate to configure the app?

  • settings.py
  • urls.py
  • apps.py
  • wsgi.py

Answer: apps.py. startapp creates apps.py containing the app's configuration class.

Which file holds an app's database models?

  • views.py
  • admin.py
  • tests.py
  • models.py

Answer: models.py. models.py is where you define an app's database tables as model classes.

What happens if you create an app but never add it to INSTALLED_APPS?

  • Django does not detect its models or migrations
  • Django auto-registers it on restart
  • The app runs but slower
  • Migrations are created automatically

Answer: Django does not detect its models or migrations. Until registered, Django ignores the app's models, migrations, templates, and tests.

From which directory should you run startapp?

  • The home directory
  • The folder containing manage.py
  • The migrations folder
  • The static folder

Answer: The folder containing manage.py. startapp is run from the project folder that contains manage.py.

Continue this course

Frequently asked questions

What is the difference between a Django project and a Django app?

A project is the overall website: it holds the global configuration (settings.py), the root URL routing table (urls.py), and the server entry points (wsgi.py and asgi.py). An app is a self-contained module inside that project that implements one specific feature — a blog, a poll, a shopping cart, or user accounts. A single project can contain many apps, and one well-written app can be reused across multiple projects. Think of the project as the building and each app as a room with a clear purpose.

How many apps should a Django project have?

There is no fixed number — it depends on how many distinct features your site has. A small site might have just one or two apps, while a large site can have a dozen or more. The guiding principle is the single-responsibility idea: each app should do one thing well. If an app starts handling unrelated concerns (for example a 'blog' app that also manages payments), that is a signal to split it into separate apps. Smaller, focused apps are easier to test, reuse, and reason about.

Do I have to register every app in INSTALLED_APPS?

Yes. Running 'python manage.py startapp blog' creates the app's folder, but Django does not know the app exists until you add it to the INSTALLED_APPS list in settings.py. Until you register it, Django will not detect its models, will not create migrations for it, will not load its templates from the app directory, and will not run its tests as part of the project. Registering the app is what links the standalone folder into the running project.

What does startapp create, and can I create the files myself?

The 'startapp' command generates a folder containing __init__.py, apps.py (the app configuration class), models.py (database models), views.py (request handlers), admin.py (admin site registrations), tests.py, and a migrations/ folder with its own __init__.py. You could technically create these files by hand, but using startapp guarantees the correct structure and naming, which Django relies on for autodiscovery. Most developers always use startapp and then add extra files like urls.py or forms.py themselves.