Declaring models elsewhere than in "models.py" AND dynamically
I have an application that splits models into different files.
Actually the folder looks like :
>myapp
__init__.py
models.py
>hooks
...
...
myapp
don't care about what's in the hooks
, folder, except that there are models, and that they have to be imported somehow, and installed by syncdb. So, I put this in myapp.__init__.py
:
from django.conf import settings
for hook in settings.HOOKS :
try :
__import__(hook)
except ImportError as e :
print "Got import err !", e
#where settings.HOOKS = ("myapp.hooks.a_super_hook1", ...)
In order for this code to work, the models in hooks
have
class Meta:
app_label="my_app"
The problem is that it doesn't work when I run syncdb
.
So I tried successively :
1)
for hook in settings.HOOKS :
try :
exec ("from %s import *" % hook)
-> doesn't work either : syncdb doesn't install the models in hooks
2)
from myapp.hooks.a_super_hook1 import *
-> This works
3)
exec("from myapp.hooks.a_super_hook1 import *")
-> This works to
So I checked that in the test 1), the statement executed is the same than in tests 2) and 3), and it is exactly the same ...
Any idea ???
EDIT : The question could be summarized to :
I declared models outside of "models.py", where to put MY import code, so that syncdb
finds the mode开发者_如何学Cls ?
Django know of all models that are defined anywhere in your project, so you only need to make sure that the code where they are defined gets executed. This usually happens when you import the module in which the models are defined.
The other thing which is important to know is that the app_label
attribute of the Meta
class inside your models needs to be set to the package name of your app (myapp
in your example). This is necessary, because syncdb
will only install models in the database from apps that are listed in your INSTALLED_APPS
setting.
Regarding to your setup described in your question, you need to:
- make sure that the module where the model is defined gets imported
- set the
app_label
attribute in the model'sMeta
class tomyapp
- put
myapp
into yourINSTALLED_APPS
setting
Additional information:
Another requirement in django for making the syncdb
work on your models is, that the app in which the models are defined (to which app_label
is set to) needs a models.py
file even if its empty. But as described in your question you already have this file.
Ok ... I've got the damn thing.
When importing models, syncdb tries to import what it finds. If the import fails, then it is post-poned to be tried later ! That's why :
for hook in settings.HOOKS :
try :
__import__(hook)
except ImportError as e :
print "Got import err !", e
doesn't work with syncdb : because the import error is caught, and not transmitted, then the models import will never be post-poned. So right code to do this is simply :
for log_hook in settings.LOG_HOOKS :
try :
__import__(log_hook)
except ImportError as e :
raise e
The try... except
is probably useless in this case.
Assuming you have a file called users_models.py
in hooks
folder:
You could say from hooks.users_models import *
in myapp.__init__.py
right ? That will be picked up by syncdb
for sure.
精彩评论