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.
# 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.
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.
# 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.
# 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.
Project, App, startapp, INSTALLED_APPS, Modularity