Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

Django Create App: The startproject, the startapp, the Structure, and the Right Way to Add an App to a Project

Sean

Platform Writer

Jun 23, 2026
6 min read

Django’s create app flow is two commands: django-admin startproject myproject creates the project (the settings, the URL conf, the WSGI), and python manage.py startapp myapp creates the app (the models, the views, the migrations, the admin). The right answer is one app per logical concern (a users app, a blog app, an api app), the app added to INSTALLED_APPS, the models defined in the app, the migrations run from the project. The mistake every team makes: the team creates a single core app with everything, the project becomes unmaintainable at 50 models.

Django Create App: The startproject, the startapp, the Structure, and the Right Way to Add an App to a Project

Table of contents

The startproject — the project shell

django-admin startproject myproject creates the project directory. The result is a myproject/ directory with manage.py (the Django CLI), a myproject/ subdirectory with settings.py, urls.py, wsgi.py, asgi.py. The right answer is the default layout for a small project. The wrong answer is to flatten the layout — the team has settings.py next to models.py, the team loses the project’s separation from the app’s.

The startapp — the app skeleton

python manage.py startapp myapp creates the app directory. The result is a myapp/ directory with models.py, views.py, admin.py, apps.py, migrations/, tests.py. The right answer is the default layout for a new app. The right answer is to add the app to INSTALLED_APPS in settings.py (INSTALLED_APPS = [..., 'myapp']), the wrong answer is to skip this step — Django does not detect the app, the migrations are not run.

The right granularity — one app per logical concern

The right answer for app granularity is one app per logical concern. A users app for authentication, a blog app for the blog, an api app for the REST API, a payments app for the payment processing. The right answer is to have 5-10 apps for a medium project, the wrong answer is a single core app with everything — the project becomes unmaintainable at 50 models, the team’s tests are slow because the test runner loads every model.

The models — the app’s data layer

The models are defined in myapp/models.py. The right answer is one model per file for a large model (the model + the manager + the methods), the right answer is to group small related models in one file. The right answer for a model’s name is the singular noun (Post, not Posts). The right answer for a foreign key is to use the string reference ('blog.Post') to avoid circular imports.

The migrations — the app’s schema

The migrations are in myapp/migrations/. The right answer is to run python manage.py makemigrations to create the migration, python manage.py migrate to apply the migration. The wrong answer is to edit the migration by hand — the team’s migration is out of sync with the model, the team’s deploy fails.

The gotcha: the team’s migrations/ directory has a __init__.py, and the team that deletes the file breaks the migration discovery. The right answer is to leave the __init__.py in place, the wrong answer is to delete it because the team thinks it’s an old Python 2 thing.

The views — the app’s HTTP layer

The views are defined in myapp/views.py. The right answer is class-based views (CBVs) for the standard CRUD operations, function-based views (FBVs) for one-off endpoints. The right answer is to keep the views thin (the view parses the request, calls the service, returns the response), the wrong answer is to put the business logic in the view — the team’s view is 500 lines, the team’s tests are slow, the team’s reuse is impossible.

The admin — the app’s admin registration

The admin is registered in myapp/admin.py. The right answer is to register every model in the admin (admin.site.register(Post)), the wrong answer is to skip the admin for a model the team thinks is ‘internal’ — the team’s on-call needs to fix a data issue, the team’s on-call does not have an admin UI.

The tests — the app’s test suite

The tests are in myapp/tests.py (or myapp/tests/ for a larger test suite). The right answer is to write a test for every model, a test for every view, a test for every service. The right answer is to use Django’s TestCase, the wrong answer is to use unittest.TestCase — the team loses the database fixtures and the test client’s conveniences.

How this fits the rest of the stack

The infrastructure question is a small piece of a larger pattern: the team’s runtime, storage, database, secret store, logs, and deployment platform are all parts of the same platform. The right answer is to model the full stack before the project ships, not after. The RunxBuild hosting calculator is the right place to do that exercise — pick the runtime, the memory tier, the storage, the secret store, and the egress, and the calculator shows what the deploy actually costs at the team’s actual usage.

Useful related references:

FAQ

How do I create a Django app?

Two commands: django-admin startproject myproject creates the project, python manage.py startapp myapp creates the app. Add the app to INSTALLED_APPS in settings.py.

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

A project is the settings, the URL conf, the WSGI — the shell. An app is a self-contained module (models, views, admin) that does one thing. A project contains multiple apps.

How many apps should a Django project have?

5-10 apps for a medium project. The right answer is one app per logical concern (a users app, a blog app, an api app).

What is the right granularity for a Django app?

One logical concern per app. The wrong answer is a single core app with everything — the project becomes unmaintainable at 50 models.

How do I run a migration in Django?

python manage.py makemigrations creates the migration, python manage.py migrate applies it. The right answer is to run makemigrations after every model change.

How do I register a model in the Django admin?

In myapp/admin.py: from .models import Post; admin.site.register(Post). The right answer is to register every model, not just the ‘user-facing’ ones.

Should I use class-based views or function-based views in Django?

CBVs for the standard CRUD operations, FBVs for one-off endpoints. The right answer is to keep the views thin (call the service, return the response).

How do I write tests in Django?

Use Django’s TestCase, write tests in myapp/tests.py (or myapp/tests/). The right answer is a test for every model, every view, every service.

#Django#Python#App#Tutorial#Backend