This is a pretty simple django patterns question. My manager code usually lives in models.py, but what happens when models.py is really huge? Is there any other alternative pattern to letting your manager code live in models.py for maintainability and to avoid circular imports?
A question may be asked as to why models.py is so huge, but let's just assume it's size and breadth of utility is justified.
I prefer to keep my models in models.py and managers in managers.py (forms in forms.py) all within the same app. For more generic managers, I prefer to keep them in core.managers if they can be re-used for other apps. In some of our larger apps with models/modelname.py that will contains a manager and the model code which doesn't seem bad.
Your best bet with a large set of models is to use django modules to your advantage, and simply create a folder named models. Move your old models.py into this models folder, and rename it __init__.py. This will allow you to then separate each model into more specific files inside of this model folder.
You would then only need to import each model into your __init__.py's namespace.
So, for instance, you might want to separate it into:
yourapp/
models/
__init__.py # This file should import anything from your other files in this directory
basic.py # Just an example name
morespecificmodels.py # Just an example name
managers.py # Might want to separate your manager into this
Then your __init__.py can just be:
from basic import * # You should replace * with each models name, most likely.
from managers import YourManager # Whatever your manager is called.
This is the structure that I use when my model files get huge, however I try to separate things into more pluggable apps as often as possible - so this is rarely used by me.
Hope this helps.
I always place mine in managers.py. If you have a circular import issue remember that a) You can reference the model class for a manager at self.model, and b) You can do imports inside of functions.
What I did when building Django apps was to create a [modelname].py file with just the specific model code, manager code and sometimes form code and used an __init__.py file to import then all in the models directory. This helped me atleast in keeping it managable.
Related
Since I am a beginner in Django and Python world and I am currently trying to make a real project in it Django but being a java programmer by heart and I generally believe in breaking down application in parts as small as possible.
So I was trying to move /models.py file to /models/myModels.py, but when I try to do the migrations it was an unsuccessful attempt, so I want to ask whether we could relocate and break default models.py, views.py(like we could break tests files and also put them in specific packages following the naming conventions) or we have to accommodate all code in a single file. Although I firmly believe that we could do this but right now I am unable to find any way to do this.
Any help is greatly appreciated.
The trick here is that you cannot directly replace:
models.py
class ModelOne(...):
...
class ModelTwo(...):
...
with:
/models
model_one.py
class ModelOne(...):
...
model_two.py
class ModelTwo(...):
...
as now from models import ModelOne will fail, Python doesn't know how to find ModelOne within the directory. One fix is to change the imports, to e.g.
from models.model_one import ModelOne
but this may mean lots of changes throughout your app; it's much easier to use an __init__.py to determine what should be importable from models, making the directory a package that appears to Python to be identical to the single file you had before:
/models
__init__.py
from model_one import ModelOne
from model_two import ModelTwo
model_one.py
class ModelOne(...):
...
model_two.py
class ModelTwo(...):
...
See e.g. https://docs.python.org/2/tutorial/modules.html#packages for more information.
How can I import all models in the settings.py in INSTALLED_APPS? When i`m trying to insert some model there is an error occurred: "no models named app1_model"
-ProjectName
--ProjectName
---models
----__init__.py
----admin.py
----app_1_model
----....
----app_n_model
---templates
---__init__.py
---settings.py
---urls.py
---wsgi.py
--manage.py
^ Structure of project ^
The INSTALLED_APPS is for apps not for models. Models are classes that live within your app, usually in /«app_name»/models.py.
I think you have misunderstood how a Django project is structured. Try working through a tutorial example.
a typical structure:
/«project»/«app_name»/models.py
and in settings:
INSTALLED_APPS = [ ... '«app_name»' ... ]
Your path will contain the base project directory, so you can import your app where you need it.
And to use them:
from «app_name».models import *
Although it is always best not to import *, instead, name the classes you wish to import.
To answer the question in the comment:
If you don't like the idea of storing all your models in one file (even though it is normal to do this), you can create a module called models. To do this, create a directory called /«project»/«app_name»/models, inside it put __init__.py (to declare it as a module) and then create your files inside there. You then need to import your file contents into the module in __init__.py. You should read about Python modules to understand this.
To answer the second comment question:
To view models in admin, you should create an admin file with model admin objects.
And finally:
Please read through the tutorials to ensure you have a thorough understanding of Django. Otherwise you're wasting your own time!
I have a very long forms.py and I'd like to split it to smaller parts with as few as possible changes in the code.
Any ideas?
I can't comment, so I'm writing answer. The other thing you can do is to create a forms
directory(remember about __init__.py) in an app directory and split your forms to formone.py, form2.py,...
Then you can import form like that from myapp.forms.formone import FormOne
Or in the __init__.py you can place code:
from formone import *
from form2 import *
And you can import forms with from myapp.forms import FormOne
The main reason that we put Django form classes into a forms.py file is convention. It makes it easy for others to look at your application and know what kinds of things he or she will find in any given file. It's good to follow conventions, but it's not the law and you're free to organize your code as you please.
Here's what I'd do:
First of all, see if you can reduce the amount of code by factoring out duplicated code. Common validation logic could be pulled into custom validators. Forms that share fields or functionality could inherit from a common parent.
If you have created custom field classes, you could separate all those into a file called something like formfields.py in the application directory, and simply import them into forms.py. Likewise, if you have custom validators, you can take those out and import them.
If none of that reduces filesize enough for you, I would split up my form classes by function into several files, e.g. forms_user.py, forms_products.py, forms_data_entry.py or whatever. That way, it's still obvious what we will find in a given file. You will have to change import statements wherever your old forms are referenced, but those should be the only changes necessary.
If you really want to make as few changes as possible, splitting forms.py into multiple files by function (forms_user.py, forms_product.py) is the easiest.
If you have time to refactor or are starting a new project, the best solution is to make a new django app for each component of your project (e.g. users, projects...) each with its own forms.py file. If a single django app gets too big lots of things stop scaling (models.py, views.py etc.) and maintenance gets harder across the board.
I have multiple Django apps, and I have some code in one of my models.py that really applies to all of the apps. Is there a way to move it somewhere generic, outside of a specific app folder?
Examples of non app specific code I have:
def update_groups(sender, user=None, ldap_user=None, **kwargs):
...
django_auth_ldap.backend.populate_user.connect(update_groups)
A function to correctly identify users, and connect to the correct signal.
I also have a model proxy of django.contrib.admin.models.LogEntry and a modelAdmin of that model proxy so users in the admin site can view the change history. But these really don't belong in any one app's models.py.
Well, just create a python module somewhere in your project and then refference it in your models. To do this, you need a directory with __init__.py file:
helpers/
__init__.py
functions.py
Put your code into the functions.py and in any other place you will be able to:
from helpers.functions import update_groups
post_save.connect(update_groups)
Name of the module is up to you, ofcourse.
You could create a template app that could be used or extended (class hierarchy) by all your other apps that could use that code.
__init__.py in my project's directory seems to be a good place to put this stuff. It gets run right away when the server starts so it's available to everything else. It seems to work fine so far.
I'd like to move my models to a separate directory, similar to the way it's done with Rails to cut down on code clutter. Is there any way to do this easily?
Thanks,
Collin
I assume you're using the basic webkit and not Django or something fancy. In that case just create a subdirectory called models. Put any python files you use for your models in here. Create also one blank file in this folder called __init__.py.
Then in your main.py or "controller" or what have you, put:
import models
at the top.
You just created a python package.
Brandon's answer is what I do. Furthermore, I rather like Rails's custom of one model per file. I don't stick to it completely but that is my basic pattern, especially since Python tends to encourage more-but-simpler lines of code than Ruby.
So what I do is I make models a package too:
models/
models/__init__.py
models/user.py
models/item.py
models/blog_post.py
In the main .py files I put my basic class definition, plus perhaps some helper functions (Python's module system makes it much safer to keep quickie helper functions coupled to the class definition). And my __init__.py stitches them all together:
"""The application models"""
from user import User
from item import Item
from blog_post import BlogPost
It's slightly redundant but I have lots of control of the namespace.