开发者

Declaring models elsewhere than in "models.py" AND dynamically

开发者 https://www.devze.com 2022-12-29 03:04 出处:网络
I have an application that splits models into different files. Actually the folder looks like : >myapp

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:

  1. make sure that the module where the model is defined gets imported
  2. set the app_label attribute in the model's Meta class to myapp
  3. put myapp into your INSTALLED_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.

0

精彩评论

暂无评论...
验证码 换一张
取 消