Oh, don't do that. Very bad. :-(
Importing models means they start to get registered with the app_cache
(to track reverse relations, amongst other things), which means we need
to know about other applications, which is specified in a setting, which
is in the settings file. Spot the circular dependency.
In settings.py, you can't really expect to use anything from Django
itself. You can write arbitrary Python code that talks to other parts of
your system or whatever, but large portions of the core of Django
requires settings to have been fully imported before they can be used.
So you cannot use them inside settings itself.
Perhaps if you explain what you're trying to achieve we could suggest an
alternate route.
Regards,
Malcolm
--
I don't have a solution, but I admire your problem.
http://www.pointy-stick.com/blog/
Now you see why all the Django settings like this are strings. :-)
> And then, in some view I do:
>
> from django.conf import settings
> splitted = settings.MY_MODEL_FORM.split('.')
> module = __import__(splitted[0])
> for i in range(len(splitted)-1):
> module = getattr(module, splitted[i+1])
> my_model_form_class = module
> my_model_form = my_model_form_class()
You're certainly on the right track. However, you're not using the full
power of __import__(). Have a read of the Python docs (in the Library
Reference, have a look at builtin functions. It's the first entry in
§2.1). Basically, the trick is that you can pass a dotted string form as
the first argument to __import__. However, you also need to watch out
for what __import__ returns (explained in the docs). So, typically,
you'll be doing this:
klass = __import__(settings.MY_MODEL_FORM, {}, {}, '')
where I've used "klass" instead of "my_model_form_class". Passing '' as
the last argument means that klass will now be a reference to what you
expect (try leaving it off and look at what klass is, if you're
interested).
Not surprisingly, Django does this sort of thing all over the place.
See, for example, django/template/loader.py or
django/db/models/loader.py (just search for __import__). It's the
standard way to import something dynamically on those rare occasions
when you need to.
Regards,
Malcolm
--
Plan to be spontaneous - tomorrow.
http://www.pointy-stick.com/blog/
Hmm. Are you perhaps trying to execute this whilst myapp.forms is still
being imported? For example, something that myapp.forms imports if
running this line of code? That won't work (until a module is fully
imported, its name exists in sys.modules to prevent circular imports,
but the value (module) attached to that name is empty, so you cannot
access the internals of a module until it's been fully imported).
If that's not the case, can you import 'myapp.forms' using the above
technique (you're probably right that a list is needed at the end, btw;
I posted without actually checking too carefully)? What I'm trying to
work out is where in the dotted import path it all goes wrong.
My first thought was that you didn't have "myapp" on your Python path
(the parent directory of myapp has to be on the Python path), but that
would probably generate a message saying it couldn't import "myapp",
rather than something about "MyModelForm" (guessing; I didn't test it).
So, how far can you get down the import chain here?
(a) klass = __import__("myapp", {}, {}, [''])
(b) klass = __import__("myapp.forms", {}, {}, [''])
(c) klass = __import__("myapp.forms", {}, {}, ['MyModelForm'])
None of these are what you want, but it might give some idea as to where
the problem really lies.
Malcolm
--
The cost of feathers has risen; even down is up!
http://www.pointy-stick.com/blog/
The .pyc file thing is a red herring here. Python will byte compile
files it imports and save them to disk, if it can (i.e. if it has write
permission). However, if it cannot do so, no problems, it's just a bit
slower the next time (because it has to recompile).
So if you're in a position where a .pyc file loads and the
corresponding .py file does not, something is seriously messed up. I
doubt that's going on.
That would lend evidence to my wondering if you are running the
__import__ statement from something that is being imported by forms.py
(so forms.py hasn't finished importing at the time you execute that line
and, thus, forsm.MyModelForm wouldn't exist).
Still, a quick test here shows that __import__ does save the .pyc file
when the calling process had write-permission to the directory I was
importing from.
Regards,
Malcolm
--
Quantum mechanics: the dreams stuff is made of.
http://www.pointy-stick.com/blog/
Oh, doh! I'm an idiot. The answer was there all along.
You can't do "import myapp.models.MyOtherModel", because MyOtherModel
isn't a *module*. It's something inside a module. That's just normal
Python behaviour.
So you have to do
module = __import__("myapp.forms", {}, {}, ['MyModelForm'])
(using either 'MyModelForm' or '' in the last component). Then
klass = module.MyModelForm
Of course, in your case, that means splitting off the last dotted piece
of the string to work out the form class. This is exactly what we do in
django.template.loader.find_template_source(), for example, to separate
the template loader function from the model it's contained in.
I'm so sorry for misleading you for a little while there. Complete brain
failure on my part. But it all makes perfect sense now.
Regards,
Malcolm
--
Depression is merely anger without enthusiasm.
http://www.pointy-stick.com/blog/
import importlib
module_name, name = path.rsplit('.', 1)
return getattr(importlib.import_module(module_name), name)