Create classes at runtnime
Ian
ian.g.kelly at gmail.com
Fri Feb 4 17:56:48 EST 2011
On Feb 4, 2:32 pm, Peter Otten <__pete... at web.de> wrote:
> > (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?
>
> The metaclass does indeed take a dictionary argument where you can provide
> class attributes, e. g.:
>
> >>> C = type("C", (), dict(a=1, b=lambda self: 42))
> >>> C().a, C().b()
>
> (1, 42)
This approach will basically work, but since you're subclassing the
Django ModelForm, note that it already has its own metaclass:
>>> django.forms.ModelForm.__class__
<class 'django.forms.models.ModelFormMetaclass'>
So you will need to either subclass ModelFormMetaclass for your
metaclass and override the __init__ method, or modify what Peter
posted like so:
>>> C = django.forms.ModelForm.__class__("VirtualUserLimitForm", (django.forms.ModelForm,), dict(a=1, b=lambda self: 42))
Cheers,
Ian
More information about the Python-list
mailing list