Separation of business logic and data access in django
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Django, business logic and data access often start out tangled together in views, models, or forms. As the project grows, separating them makes the code easier to test, easier to change, and less dependent on where the data happens to come from.
What the Separation Means
Business logic is the rule set of the application: who can place an order, when an invoice is valid, or how a workflow progresses. Data access is the part that queries and writes the database through the ORM.
Those two concerns are related, but they are not the same. A pricing rule should not need to know how a queryset is constructed, and a repository or queryset helper should not contain half the checkout workflow.
A Simple Django Example
Here is one way to separate them.
The service coordinates the rule that an order must have items and the workflow that changes its status. The ORM is still used, but the business decision stays in one place.
Keep Query Logic Focused
Data access can still live in querysets, managers, or thin repository-style helpers.
This keeps filtering and retrieval logic close to the model without stuffing domain workflow into the queryset layer.
Why Views Should Stay Thin
Views are good at HTTP concerns such as reading request data, returning responses, and mapping exceptions to status codes. They are not a great long-term home for business rules.
A thin view can simply delegate:
That code is intentionally minimal. The view handles the web request. The service handles the application rule.
Do Not Over-Engineer It
This separation does not mean every project needs a heavy repository layer or a giant service directory from day one. Small Django apps often do fine with modest structure. The point is to keep responsibilities clear as complexity increases.
A good practical rule is:
- Query construction belongs near the data layer
- Business rules belong in services or domain-focused functions
- HTTP formatting belongs in the view layer
That separation becomes more valuable as workflows become more complex or more business rules accumulate. It also makes tests easier to target. And easier to maintain.
Common Pitfalls
- Putting all business rules into models can create fat models that are hard to test and hard to reuse.
- Putting all ORM calls into views mixes HTTP concerns with application rules.
- A service layer should organize business behavior, not become a second place for random database helpers.
- Separation helps most when it follows real responsibilities, not when it becomes architecture for architecture's sake.
Summary
- Business logic is about application rules, while data access is about reading and writing data.
- Django projects often benefit from moving business workflows into services or domain-focused functions.
- Querysets and managers are good places for reusable query logic.
- Thin views plus focused services usually scale better than mixing everything into one layer.

