Project vs App Architecture

Difficulty: Beginner

Understanding the distinction between a Django project and a Django app is fundamental to building well-organized Django applications. A project is the entire web application - it contains configuration, settings, and a collection of apps. An app is a self-contained module that handles a specific piece of functionality. A project can contain multiple apps, and an app can be reused across multiple projects.

Think of it this way: a project is like a company, and apps are like departments within that company. A company named 'TechStore' might have a 'products' department, an 'orders' department, a 'users' department, and a 'reviews' department. Each department handles its own responsibilities but they all work together as part of the same company. Similarly, a Django project might have a 'products' app, an 'orders' app, a 'users' app, and a 'reviews' app.

You create a new app using 'python manage.py startapp appname'. This generates a directory with a predefined structure: __init__.py (makes it a package), admin.py (admin site registration), apps.py (app configuration), models.py (database models), tests.py (test cases), views.py (view functions/classes), and a migrations/ directory (database migration files). You may also want to create additional files like urls.py, forms.py, serializers.py, and templatetags/ as your app grows.

After creating an app, you must register it in the project's settings.py by adding it to the INSTALLED_APPS list. Until you do this, Django will not know about your app - it won't discover its models, templates, static files, or management commands. You can reference the app by its name (e.g., 'blog') or by its full AppConfig path (e.g., 'blog.apps.BlogConfig'), with the latter being the recommended approach.

Good app design follows the single responsibility principle. Each app should do one thing and do it well. An app named 'blog' should handle blog posts, categories, and comments - not user authentication or payment processing. This separation makes your code more maintainable, testable, and reusable. If you build a 'blog' app that is truly self-contained, you could potentially drop it into an entirely different Django project with minimal changes.

Django itself follows this pattern with its contrib apps. django.contrib.auth handles authentication, django.contrib.admin provides the admin interface, django.contrib.sessions manages sessions, and so on. Each is a separate app that can theoretically be removed or replaced. This demonstrates the power of Django's app architecture at the framework level.

As your project grows, you may want to organize apps into subdirectories or use a 'apps/' directory to keep things tidy. Some teams create an 'apps/' folder and put all their custom apps inside it. Others organize by feature domain. The key principle is consistency - pick a convention and stick with it throughout the project.

Code examples

Creating and Registering an App

# Create a new app
python manage.py startapp blog

# Register it in settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Your apps
    'blog.apps.BlogConfig',   # Recommended: use AppConfig
]

After running startapp, you must add the app to INSTALLED_APPS in settings.py. Using the AppConfig path (blog.apps.BlogConfig) is recommended over just the app name string because it allows Django to detect app configuration properly.

App Directory Structure

blog/
    __init__.py       # Makes this a Python package
    admin.py          # Admin site registration
    apps.py           # App configuration class
    models.py         # Database models
    tests.py          # Test cases
    views.py          # View functions/classes
    migrations/       # Database migrations
        __init__.py

# You often add these manually:
    urls.py           # App-specific URL patterns
    forms.py          # Form classes
    serializers.py    # DRF serializers (if using API)
    templates/        # App-specific templates
        blog/
            post_list.html
    static/           # App-specific static files
        blog/
            style.css

Django's startapp creates the core files. You typically add urls.py for routing, forms.py for form classes, and templates/ and static/ directories. Template and static subdirectories mirror the app name to avoid naming collisions.

AppConfig Class

# blog/apps.py
from django.apps import AppConfig

class BlogConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'blog'
    verbose_name = 'Blog & Articles'

    def ready(self):
        # Import signal handlers when the app is ready
        import blog.signals  # noqa: F401

The AppConfig class configures app metadata. 'name' must match the app's Python package name. 'verbose_name' is used in the admin. The ready() method runs when Django starts and is the right place to import signal handlers.

Multi-App Project Example

# A typical e-commerce project structure
ecommerce/              # Project directory
    manage.py
    ecommerce/           # Project settings package
        settings.py
        urls.py
        wsgi.py
    products/            # Products app
        models.py        # Product, Category models
        views.py
        urls.py
    orders/              # Orders app
        models.py        # Order, OrderItem models
        views.py
        urls.py
    users/               # Custom user app
        models.py        # CustomUser model
        views.py
        urls.py
    reviews/             # Reviews app
        models.py        # Review model
        views.py
        urls.py

Each app handles one domain of the business logic. Products manages the catalog, orders handles purchasing, users manages authentication and profiles, and reviews handles product feedback. They can reference each other through Django's ORM relationships.

Key points

Concepts covered

Project, App, startapp, INSTALLED_APPS, Modularity