I\'m trying to update certain fields a ModelForm, these fields are not fixed. (I have only tutor
that is autopopulated by the view)
Model:
Put your form fields as nullable and with "clean" methods you can add logic to fields ex:
class SessionForm(forms.ModelForm):
def clean_end_date(self):
cd = self.cleaned_data
if (cd["start_date"] and cd["end_date"]) and cd["end_date"] < cd["start_date"]:
raise forms.ValidationError("WTF?!")
if not (cd["start_date"] or cd["end_date"]):
raise forms.ValidationError("need one date")
return cd['end_date']
If you want to change value, use a different value to the return statement.
This is what you may need for validation.
If you want, you may copy GET dictionary in your view and update values before instanciate your form
def my_view(request):
r_data = request.GET.copy()
r_data.merge(request.POST)
data = dict([(key, my_function(key, value)) for key, value in r_data.iteritems() if key in MyForm.fields])
form = MyForm(data=data)
[...]
hopes it help.
Your question suggests that you have a requirement that uses same model but different fields are hidden in your ModelForm, based on your needs.
If I understand your question, then you need to Create two different ModelForm based class, both these classes have same model value inside the Meta class. Exclude and include the fields you need. So now you have different ModelForm classes which you can call inside your view logic.
With this you will have two different forms that depend on same model, with different default fields.
With clever url and view design you will be able to use the above idea to serve multiple forms from same model.
You can invoke form's constructor like this:
class SessionForm(forms.ModelForm):
class Meta:
model = Session
exclude = ['tutor', 'start_time']
def __init__(self, your_extra_args, *args, **kwargs):
super(SessionForm, self).__init__(*args, **kwargs)
if need_end_time_start_time(your_extra_args):
self.fields['start_time'] = forms.DateTimeField()
To use this class, you have to pass an argument "your_extra_args" to your form:
session_form = SessionForm('foo')
I've had to do something similar before, and while it isn't exactly pretty, it is quite effective. It involves dynamically creating a type at runtime, and using that type. For some documentation, you can see DynamicModels for django.
Here we go.. your requirements.
So, some code:
def create_form(model, field_names):
# the inner class is the only useful bit of your ModelForm
class Meta:
pass
setattr(Meta, 'model', model)
setattr(Meta, 'include', field_names)
attrs = {'Meta': Meta}
name = 'DynamicForm'
baseclasses = (forms.ModelForm,)
form = type('DynamicForm', baseclasses, attrs)
return form
def my_awesome_view(request):
fields = ['start_time', 'end_time']
form = create_form(Session, fields)
# work with your form!