My models.py is spanning 2000 lines with scores of model classes - is there some standard convention to keep each class in separate model files ? And how do we import the whole 20+ models in the models.py file ?
Yes there is a way, You can create a separate file like separate_models.py that have models A, B, C. Then in your models.py just import it and run migrations command it will be migrated and work like rest of your models defined in models.py.
Note: Just Import your separate_models in models.py and run migrations command, Also in your admin.py you can register these models same as you do with models.py models.
from .separate_models import (
A, B, C, etc...
)
I donāt see why you shouldnāt be able to do it, even though I didnāt have to do it myself. It must be no different to import a model from another application for use in your own model. In the same folder as your models.py,
create your files modelA.py
modelB.py
ā¦
then use them in models.py
, that should do the trick.
See CookBookSplitModelsToFiles ā Django
Yes, the reference is old, and their note regarding the Meta class no longer applies, but this is a standard pattern for creating a module for models instead of a single file.
(Side note: Please do your developers a favor and do not make this 1 model per file. Python is not Java. At a minimum allow for some common groupings of directly related models in a common file. Your developers will thank you for it.)
Thank you for your feedback, @KenWhitesell . I understand that my proposal to split models into multiple files might seem counterintuitive, and I acknowledge your concerns about logically grouping models. However, Iād like to understand better why this approach could be problematic. In my understanding, Django does not restrict us to one model per file - itās entirely feasible to distribute models across multiple files for clarity and organization, especially in larger projects. For instance, in a large project, we might have separate files such as order_models.py, customer_models.py, etc., grouping related models logically, while then importing them into models.py for centralized management. This method seems to be a common practice for managing complex projects, improving readability and maintainability. That said, Iām open to your insights and experiences on why this approach might not be ideal, or how it could be improved."
Project structure example:
myapp/
__init__.py
models/
__init__.py
user.py
product.py
order.py
...
myapp/models/user.py
:
from django.db import models
class User(models.Model):
# Define User model fields and behavior here
...
myapp/models/product.py
:
from django.db import models
class Product(models.Model):
# Define Product model fields and behavior here
...
In myapp/models/order.py
:
pythonCopy code
from django.db import models
class Order(models.Model):
# Define Order model fields and behavior here
...
And finally, in myapp/models/__init__.py
:
from .user import User
from .product import Product
from .order import Order
# Import other models here as needed
...
With this structure, each model is placed in its own file for better organization and clarity, especially in large projects. Each model is then imported into the __init__.py
file for centralized management and simplified importing into other parts of the application. This approach allows for maintaining smaller, more manageable model files while offering flexibility for future project growth.
My experience has been that āclarity and organizationā - especially in larger projects, is not enhanced by dramatically increasing the number of files involved. In fact, I have found the exact opposite to be true.
We donāt even begin to think about splitting apart our models.py files until theyāre at least 2000 lines, and will let them get to about 2500 before taking action. (And, in some cases - typically when external databases are involved, that āactionā ends up being ādo nothingā because we recognize thereās no benefit in those cases by splitting up the models.)
And, in those cases where we do choose to do something, as often as not it ends up being a situation where we split a whole chunk of functionality off as a separate app.
I can respect the fact that you have that opinion. We (the development team I am a part of) donāt share that opinion and disagree with the conclusion. We all have backgrounds with large Java-based projects and have concluded that the āone-class-per-fileā default standard is extremely counter-productive and have found much practical benefit in the āfewer-files-are-betterā approach.
Dear @KenWhitesell ,
Thank you for your detailed response and for sharing your experience with managing large Django projects. Your insights on the impact of increasing file numbers on clarity and organization are very pertinent.
I understand your perspective that splitting a models.py
file into several smaller files does not always guarantee improved readability or maintainability, especially in complex projects. However, my initial proposition was to explore the technical feasibility of separating models into distinct files within Django, not necessarily to debate its practical efficacy. To my understanding, Django technically allows this separation, although it is not a common or recommended practice in the Django community.
I fully respect your approach of functionally dividing functionalities into different applications when justified, which is different from my suggestion of distributing models across multiple files within the same application for clarity in specific cases. Your advice to favor fewer files for better overall management is well taken and will surely be helpful to many developers.
Once again, thank you for your time and for sharing your valuable insights. Your contributions greatly enhance our collective understanding of best practices in Django development.
Best regards.
Similarly, I would like to separate model Manager classes into managers.py, instead of keeping them in models.py. Then I could see the Model, and its Manager side by side if I wanted to.
Somehow Iām unable to make it happen without running into circular dependencies or ending up with Managers that throw such errors: AttributeError: āManagerā object has no attribute āget_by_zone_nameā
Is there a way to get this done? I tried apps.get_model and Meta proxy = True but without success.