Skip to content

Instantly share code, notes, and snippets.

@wiura
Created August 6, 2014 15:09
Show Gist options
  • Select an option

  • Save wiura/6fb338d05fa4b7c61371 to your computer and use it in GitHub Desktop.

Select an option

Save wiura/6fb338d05fa4b7c61371 to your computer and use it in GitHub Desktop.
Mix in fields to django model form.
"""
Mix in fields to django model form.
"""
from django.conf import settings
settings.configure()
from django import forms
from django.db import models
class Model(models.Model):
some_data = models.CharField(max_length=100)
some_extra = models.CharField(max_length=100)
class Meta:
app_label = 'test'
class AMixin(object):
__metaclass__ = forms.forms.DeclarativeFieldsMetaclass
a = forms.CharField(max_length=50)
class BMixin(object):
__metaclass__ = forms.forms.DeclarativeFieldsMetaclass
b = forms.CharField(max_length=50)
class ModelForm(forms.ModelForm):
class Meta:
model = Model
fields = ['some_data']
def save(self, *args, **kwargs):
cleaned_data = self.clean()
# Do real save instead of this
print 'cleaned_data', cleaned_data
Model(
some_data=cleaned_data['some_data'],
some_extra='%s%s' % (cleaned_data['a'], cleaned_data['b'])
)
class ModelFormMetaclassWithMixins(
forms.forms.DeclarativeFieldsMetaclass,
forms.models.ModelFormMetaclass
):
def __new__(cls, name, bases, attrs):
# new form with fields from ModelForm
new_class = super(ModelFormMetaclassWithMixins, cls).__new__(
cls, name, bases, attrs
)
# mixins waiting to be mixin
mixins = [
b for b in bases
if type(b) == forms.forms.DeclarativeFieldsMetaclass
]
# mixin fields waiting to be mixin
mixin_fields = forms.forms.get_declared_fields(mixins, attrs, True)
# mix in new fields
new_class.base_fields.update(mixin_fields)
return new_class
def get_form(name, mixins, model_form):
bases = [model_form]
bases.extend(mixins)
new_class = ModelFormMetaclassWithMixins(name, tuple(bases), {})
return new_class
data = {
'some_data': 'some_data_post',
'a': 'a_post',
'b': 'b_post'
}
form = get_form('MyForm', [AMixin, BMixin], ModelForm)(initial=data)
print 'fields', form.fields
print form.as_p()
form = get_form('MyForm', [AMixin, BMixin], ModelForm)(data)
if form.is_valid():
form.save()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment