Create classes at runtnime

Carl Banks pavlovevidence at gmail.com
Fri Feb 4 17:51:46 EST 2011


On Feb 4, 11:17 am, Marc Aymerich <glicer... at gmail.com> wrote:
> Hi!
> I need to create a pretty complex class at runtime. something like
> this one:
>
> (note: "...." means that the number of attributes can be variable)
>
> class VirtualUserLimitForm(ModelForm):
>     swap_limit = forms.CharField(max_length=100,
> initial=monitor1.default_limit)
>     memory_limit = forms.CharField(max_length=100,
> initial=monitor2.default_limit)
>     ...
>
>     class Meta:
>         model = model
>
>     def __init__(self, *args, **kwargs):
>         super(VirtualUserLimitForm, self).__init__(*args, **kwargs)
>         if 'instance' in kwargs:
>             self.fields['swap_limit'].initial =
> kwargs['instance'].monitoring.filter(monitor=monitor1)[0].current
>             self.fields['memory_limit'].initial =
> kwargs['instance'].monitoring.filter(monitor=monitor2)[0].current
>             ...
>
> I can generate all the needed code as string and then use exec(), but
> it seems ugly to me. I'm wondering if there is another way more
> elegant to do that?  metaclasses maybe? What is your recommendation?

I'd recommend against using metaclasses (in the normal way) with
Django ORM, since it (and pretty much all ORMs) already makes heavy
use of metaclasses, and I doubt those metaclasses were designed to
share metaclassing duties.

At a minimum you'd have to derive your own metaclasses from Djangos,
and that's not likely to work out well at all.

The right way to do this might be to reorganize your database.  It
seems like you have all kinds of tables with different sets of
columns, and the tables themselves are dynamic?  Like if you get some
data somewhere and it doesn't fit into an existing schema you make a
new table for it?  If that's the case then you'd be better off,
perhaps, to reorganize the tables into some kind of association list.
Put the "relational" aspect to use.  (Left as an exercise for now but
if you want pointers feel free to follow up.)

But maybe you have no control of the tables; you simply have a lot of
them and want to cut down on repetition.  Then I think a factory
function that builds a dict and passes it to type() would be
reasonable.  See the documentation of type() for explanation of
arguments.

def create_user_form(name,fields,_model):
    class Meta:
        model = _model
    dct = { 'Meta': Meta }
    for field in fields:
        dct[field] = forms.CharField(max_length=100,
> initial=monitor1.default_limit)
    return type(name,(ModelForm,),dct)


Carl Banks



More information about the Python-list mailing list