tags:

views:

108

answers:

3

Hi ! 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 models ?

A: 

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.

Maddy
Not sure why this has been downvoted. Can you provide a reason?
Maddy
Yes ! This is definitely picked by syncdb (see examples 2 and 3)... But it means that I have to hard-code the modules to import ! And that I don't want.But anyways ... why the hell does the first chunk of code doesn't work ??? That's in fact my question !!!PS : I don't know neither why you have been down-voted, as you're the one that best understood my question.
sebpiq
May be that import(first case) will work, but that doesn't make syncdb install the required model, as it(syncdb) will always be depending on the 'installed_apps' setting and will be doing the required work only based on that. Thats why the models are 'fed' to app/models.py(which syncdb is always interested in), in an 'indirect way'
Maddy
Yeah, that's right, import works but no syncdb in the first case. But then, why does syncdb works in cases 2 and 3, while the code executed is exactly the same as in 0 and 1 (I checked by printing traces) ? Maybe you actually answered this question, but in this case I didn't understand :/
sebpiq
+1  A: 

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.

Gregor Müllegger
Thanks for your answer Gregor, I already know this ... My `app_label` attributes are already set, and everything works fine if the imports succeed...Actually, before putting the imports code in the __init__ module, they where in my settings.py (at the end of the file), and evrything worked great. But it's ugly, so I wanted to put them in the associated app. So my problem is a little bit different !
sebpiq
A: 

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.

sebpiq