4 | Fundamentals of Django App Design
It’s not uncommon for new Django developers to become understandably confused by Django’s usage of the word “app.” So before we get into Django app design, it’s very important that we go over some definitions.
A Django project is a web application powered by the Django web framework.
Django apps are small libraries designed to represent a single aspect of a project. A Django project is made up of many Django apps. Some of those apps are internal to the project and will never be reused; others are third-party Django packages.
INSTALLED APPS is the list of Django apps used by a given project available in its IN- STALLED APPS setting.
Third-party Django packages are simply pluggable,reusable Django apps that have been packaged
with the Python packaging tools. We’ll begin coverage of them in chapter 21, Django’s Secret Sauce:Third-Party Packages.
page 33
4.1 The Golden Rule of Django App Design
James Bennett volunteers as both a Django core developer and as its release manager. He taught us everything that we know about good Django app design. We quote him:
“The art of creating and maintaining a good Django app is that it should follow the truncated Unix philosophy according to Douglas McIlroy: ‘Write programs that do one thing and do it well.’”
In essence, each app should be tightly focused on its task. If an app can’t be explained in a single sentence of moderate length, or you need to say ‘and’ more than once, it probably means the app is too big and should be broken up.
4.1.1 A Practical Example of Apps in a Project
Imagine that we’re creating a web application for our fictional ice cream shop called “Two Scoops.” Picture us getting ready to open the shop: polishing the countertops, making the First batches of ice cream, and building the website for our shop.
We’d call the Django project for our shop’s website two scoops project.The apps within our Django project might be something like:
- A avors app to track all of our ice cream avors and list them on our website.
- A blog app for the official Two Scoops blog.
- An events app to display listings of our shop’s events on our website: events such as Strawberry Sundae Sundays and Fudgy First Fridays.
Each one of these apps does one particular thing. Yes, the apps relate to each other, and you could imagine events or blog posts that are centered around certain ice cream avors, but it’s much better to have three specialized apps than one app that does everything.
In the future, we might extend the site with apps like:
- A shop app to allow us to sell pints by mail order.
- A tickets app, which would handle ticket sales for premium all-you-can-eat ice cream fests.
Notice how events are kept separate from ticket sales. Rather than expanding the events app to sell tickets, we create a separate tickets app because most events don’t require tickets, and because event calendars and ticket sales have the potential to contain complex logic as the site grows.
Eventually, we hope to use the tickets app to sell tickets to Icecreamlandia, the ice cream theme park lled with thrill rides that we’ve always wanted to open.
Did we say that this was a ctional example? Ahem...well, here’s an early concept map of what we envision for Icecreamlandia:
4.2 What to Name Your Django Apps
Everyone has their own conventions, and some people like to use really colorful names. We like to use naming systems that are dull, boring, and obvious. In fact, we advocate doing the following:
When possible keep to single word names like flavors, animals, blog, polls, dreams, estimates, and finances. A good, obvious app name makes the project easier to maintain.
As a general rule, the app’s name should be a plural version of the app’s main model, but there are many good exceptions to this rule, blog being one of the most common ones.
Don’t just consider the app’s main model, though. You should also consider how you want your URLs to appear when choosing a name. If you want your site’s blog to appear at http://www.example.com/weblog/, then consider naming your app weblog rather than blog, posts, or blogposts, even if the main model is Post, to make it easier for you to see which app corresponds with which part of the site.
Use valid, PEP 8-compliant, importable Python package names: short, all-lowercase names with- out numbers, dashes, periods, spaces, or special characters. If needed for readability, you can use underscores to separate words, although the use of underscores is discouraged.
4.3 When in Doubt, Keep Apps Small
Don’t worry too hard about getting app design perfect. It’s an art, not a science. Sometimes you have to rewrite them or break them up. at’s okay.
Try and keep your apps small. Remember, it’s better to have many small apps than to have a few giant apps.
4.4 What Modules Belong in an App?
In this section we cover both the common and uncommon Python modules that belong in an app. For those with even a modicum of experience with Django, skipping to subsection 4.4.2 may be in order.
4.4.1 Common App Modules
Here are common modules seen in 99% of Django apps. ese will prove very familiar to most readers, but we’re placing this here for those just coming into the world of Django. For reference, any module ending with a slash (‘/’) represents a Python package, which can contain one or more modules.
EXAMPLE 4.1
# Common modules
scoops/
__init__.py
admin.py
forms.py
management/
migrations/
models.py
templatetags/
tests/
Over time a convention of module names has emerged for building Django apps. By following this convention across building of apps we set behaviors for ourselves and others, making examining each others code easier. While Python and Django are Flexible enough that most of these don’t need to be named according to this convention, doing so will cause problems. Probably not from an immediate technical perspective, but when you or others look at nonstandard module names later, it will prove to be a frustrating experience.
4.4.2 Uncommon App Modules
Here are less common modules, which may or may not be familiar to many readers:
EXAMPLE 4.2
# uncommon modules
scoops/
behaviors.py
constants.py
context_processors.py
decorators.py
db/
exceptions
fields.py
factories.py
helpers.py
managers.py
middleware.py
signals.py
utils.py
viewmixins.py
What is the purpose of each module? Most of these should be obviously named, but we’ll go over a few that might not be so clear.
behaviors.py : An option for locating model mixins per subsection 6.5.1.
constants.py :A good name for placement of app-level settings.If there are enough of them involved in an app, breaking them out into their own module can add clarity to a project.
decorators.py Where we like to locate our decorators. For more information on decorators, see section 9.3.
db/ Used in many projects for any custom model elds or components.
fields.py is commonly used for form elds, but is sometimes used for model fields when there isn’t enough field code to justify creating a db/ package.
factories.py Where we like to place our test data factories. Described in brief in subsection 22.3.5.
helpers.py What we call helper functions. ese are where we put code extracted from views (sub- section 16.3.3) and models (section 6.5) to make them lighter. Synonymous with utils.py
managers.py When models.py grows too large, a common remedy is to move any custom model managers to this module.
signals.py While we argue against providing custom signals (see chapter 28), this can be a useful place to put them.
utils.py Synonymous with helpers.py
viewmixins.py View modules and package scan be thinned by moving any viewmixins to this module. See section 10.2.
For all of the modules listed in this section, their focus should be at the ‘app-level’, not global tools. Global-level modules are described in section 29.1, ‘Create a Core App for Your Utilities’.
4.5 Summary
This chapter covered the art of Django app design. Specifically, each Django app should be tightly-focused on its own task, possess a simple, easy-to-remember name. If an app seems too complex, it should be broken up into smaller apps. Getting app design right takes practice and effort, but it’s well worth the effort.