models.py getting huge, what is the best way to break it up?

It’s natural for model classes to contain methods to operate on the model. If I have a Book model, with a method book.get_noun_count(), that’s where it belongs–I don’t want to have to write “get_noun_count(book)“, unless the method actually intrinsically belongs with some other package. (It might–for example, if I have a package for accessing Amazon’s API with “get_amazon_product_id(book)“.)

I cringed when Django’s documentation suggested putting models in a single file, and I took a few minutes from the very beginning to figure out how to split it into a proper subpackage.

site/models/__init__.py
site/models/book.py

__init__.py looks like:

from .book import Book

so I can still write “from site.models import Book”.


The following is only required for versions prior to Django 1.7, see
https://code.djangoproject.com/ticket/3591

The only trick is that you need to explicitly set each model’s application, due to a bug in Django: it assumes that the application name is the third-to-last entry in the model path. “site.models.Book” results in “site”, which is correct; “site.models.book.Book” makes it think the application name is “models”. This is a pretty nasty hack on Django’s part; it should probably search the list of installed applications for a prefix match.

class Book(models.Model):
    class Meta: app_label = "site"

You could probably use a base class or metaclass to generalize this, but I haven’t bothered with that yet.

Leave a Comment