I wrote a short snippet to dynamically generate all of my model forms within an app. To me, the most logical place to call this snippet is in the app’s forms.py. But this causes a circular import since I’m trying to set attributes in the module that called me, and it doesn’t exist yet. Is there an elegant way around this?
#bomgar.forms.py
import base.forms
import bomgar # bomgar is myapp
base.forms.generate_base_forms(bomgar)
#base.forms.py
from django.db import models
from django import forms
import inspect
class BaseForm(forms.ModelForm):
error_css_class = 'error'
required_css_class = 'required'
class Meta:
model=None
''' Generates a base set of forms to work off of. So I dont have to
make a billion of them by hand to start off. '''
def generate_base_forms(module):
__import__('%s.models' % module.__name__)
__import__('%s.forms' % module.__name__)
for model_name, model_class in inspect.getmembers(module.models):
if inspect.isclass(model_class):
if model_class._meta.abstract == False:
form_name=model_name+'Form'
class ModelMeta(BaseForm.Meta):
model=model_class
form_class=type(form_name,(BaseForm,), { 'Meta': ModelMeta })
setattr(module.forms, form_name, form_class)
Terminal Output
(env)Macbook:djinmanage me$ ./manage shell
Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05)
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import bomgar.models
>>> import bomgar.forms
<module 'bomgar.models' from '/Users/me/Sites/djinmanage/djinmanage/bomgar/models.pyc'>
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/me/Sites/djinmanage/djinmanage/bomgar/forms.py", line 4, in <module>
base.forms.generate_base_forms(bomgar)
File "/Users/me/Sites/djinmanage/djinmanage/base/forms.py", line 19, in generate_base_forms
print module.forms
AttributeError: 'module' object has no attribute 'forms'
>>>
Call the function to generate the forms at the end of the module, after all the required names have been bound.
EDIT:
Okay, you imported them. But you let the imports fall on the floor.
(You don’t need to catch the result of the second
__import__since they’re both the same module.)