Reputation: 236
I've attempted to modify my Django ModelForm __init__
constructor so that it will accept a passed variable ('admin'), look to see if admin == True
, and if so, make a couple of fields ('applicant_affirmation' & 'applicant_interest_stmt') display as non-modifiable. The fields are being shown as non-modifiable, as desired, but the .update()
function isn't happening because it is not getting past the if form.is_valid
check. I've checked for form.non_field_errors
and form.errors
, but nothing is there. The updates work fine if the __init__
method is commented out.
Any thoughts on what I might be missing? Admittedly I don't have a strong understanding of building a constructor yet. Help would be very much appreciated.
class ApplicationForm(ModelForm):
class Meta:
model = Application
fields = ('program', 'status', 'applicant_affirmation', 'applicant_interest_stmt', 'applicant_school', 'applicant_major', 'applicant_school_2', 'applicant_major_2', 'gpa_univ', 'estimated_grad_semester')
widgets = {
'applicant_interest_stmt': Textarea(attrs={'class': 'form-control', 'rows': 5}),
'estimated_grad_semester': Select(),
}
def __init__(self, admin, *args, **kwargs):
super(ApplicationForm, self).__init__(*args, **kwargs)
if admin:
self.fields['applicant_interest_stmt'].widget.attrs['disabled'] = 'disabled'
self.fields['applicant_affirmation'].widget.attrs['disabled'] = 'disabled'
def clean(self):
from django.core.exceptions import ValidationError
cleaned_data = super(ApplicationForm, self).clean()
applicant_interest_stmt = cleaned_data.get('applicant_interest_stmt')
applicant_affirmation = cleaned_data.get('applicant_affirmation')
if not applicant_interest_stmt:
msg = u'Please provide an interest statement.'
self._errors["applicant_interest_stmt"] = self.error_class([msg])
if not applicant_affirmation:
msg = u'Please check the affirmation checkbox.'
self._errors["applicant_affirmation"] = self.error_class([msg])
return cleaned_data
Application Model:
class Application(models.Model):
id = models.AutoField(primary_key=True)
program = models.ForeignKey(Program, verbose_name="certificate program")
status = models.ForeignKey(Status, verbose_name="application status")
applicant = models.ForeignKey(Person)
applicant_affirmation = models.BooleanField()
applicant_interest_stmt = models.TextField(verbose_name="In a few sentences, briefly explain why you are interested in this program and what you expect to get out of it")
applicant_school = models.CharField(max_length=100, verbose_name="school (primary)")
applicant_major = models.CharField(max_length=100, verbose_name="major (primary)")
applicant_school_2 = models.CharField(blank=True, max_length=100, verbose_name="school (secondary)")
applicant_major_2 = models.CharField(blank=True, max_length=100, verbose_name="major (secondary)")
gpa_univ = models.DecimalField(max_digits=3, decimal_places=2, verbose_name="GPA (university)")
estimated_grad_semester = models.CharField(max_length=5, verbose_name="estimated graduation semester")
_created = models.DateTimeField(editable=False, blank=False)
_created_by = models.CharField(max_length=150)
_updated = models.DateTimeField(editable=False, blank=False)
_updated_by = models.CharField(max_length=150)
def clean(self):
from django.core.exceptions import ValidationError
cleaned_data = super(Application, self).clean()
if not self.applicant_affirmation:
raise ValidationError('Please check the affirmation checkbox.')
if self.applicant_school_2 == '/':
self.applicant_school_2 = ''
if self.applicant_major_2 == '/':
self.applicant_major_2 = ''
def save(self, *args, **kwargs):
""" On save, update both timestamps """
self._created = datetime.datetime.now()
self._updated = datetime.datetime.now()
return super(Application, self).save(*args, **kwargs)
#end save
def update(self, *args, **kwargs):
""" On update, update only _updated timestamps """
self._updated = datetime.datetime.now()
return super(Application, self).save(*args, **kwargs)
#end update
def __unicode__(self):
return unicode(self.id)
#end unicode
class Meta:
db_table = u'certs_application'
#end meta
Snippet from views.py:
if request.POST:
app_form = ApplicationForm(request.POST)
app_form.fields['estimated_grad_semester'].widget.choices = build_semester_list('', 12)
if app_form.is_valid():
print 'form is valid...'
app_instance = get_object_or_404(Application, id=app_id)
fields = {'program': app_form.cleaned_data['program'],
'status': app_form.cleaned_data['status'],
'applicant_id': application.applicant_id,
'applicant_affirmation': app_form.cleaned_data['applicant_affirmation'],
'applicant_interest_stmt': app_form.cleaned_data['applicant_interest_stmt'],
'applicant_school': app_form.cleaned_data['applicant_school'],
'applicant_major': app_form.cleaned_data['applicant_major'],
'applicant_school_2': app_form.cleaned_data['applicant_school_2'],
'applicant_major_2': app_form.cleaned_data['applicant_major_2'],
'gpa_univ': app_form.cleaned_data['gpa_univ'],
'estimated_grad_semester': app_form.cleaned_data['estimated_grad_semester'],
'_created_by': app_instance._created_by,
'_created': app_instance._created,
'_updated_by': user.eid,
}
try:
application = Application(pk=app_id, **fields)
application.update()
except Exception, exception:
return HttpResponse('Error: ' + str(exception))
return redirect('application_view', app_id=app_id)
else:
print 'app_form is NOT valid'
else:
# -------------------------------------------
# render the application using GET
# -------------------------------------------
app_form = ApplicationForm(admin=admin_user, instance=application)
app_form.fields['estimated_grad_semester'].widget.choices = build_semester_list('', 12)
Final modifications made that resulted in the needed fix:
views.py
if request.POST:
app_form = ApplicationForm(admin=admin_user, data=request.POST)
forms.py
def __init__(self, admin, *args, **kwargs):
super(ApplicationForm, self).__init__(*args, **kwargs)
self.admin = admin
if self.admin:
self.fields['applicant_interest_stmt'].widget.attrs['readonly'] = True
self.fields['applicant_affirmation'].widget.attrs['readonly'] = True
def clean(self):
from django.core.exceptions import ValidationError
cleaned_data = super(ApplicationForm, self).clean()
if not self.admin:
applicant_interest_stmt = cleaned_data.get('applicant_interest_stmt')
applicant_affirmation = cleaned_data.get('applicant_affirmation')
if not applicant_interest_stmt:
msg = u'Please provide an interest statement.'
self._errors["applicant_interest_stmt"] = self.error_class([msg])
if not applicant_affirmation:
msg = u'Please check the affirmation checkbox.'
self._errors["applicant_affirmation"] = self.error_class([msg])
return cleaned_data
NOTE: there is still a lingering problem with getting a non-modifiable setting on the applicant_affirmation Boolean field, but I'll fix that separately from this issue.
Upvotes: 0
Views: 171
Reputation: 3042
you might want to make the admin a golobal to the class
class ApplicationForm(ModelForm):
class Meta:
model = Application
fields = ('program', 'status', 'applicant_affirmation', 'applicant_interest_stmt', 'applicant_school', 'applicant_major', 'applicant_school_2', 'applicant_major_2', 'gpa_univ', 'estimated_grad_semester')
widgets = {
'applicant_interest_stmt': Textarea(attrs={'class': 'form-control', 'rows': 5}),
'estimated_grad_semester': Select(),
}
def __init__(self, admin, *args, **kwargs):
super(ApplicationForm, self).__init__(*args, **kwargs)
self.admin = admin
if self.admin:
self.fields['applicant_interest_stmt'].widget.attrs['disabled'] = 'disabled'
self.fields['applicant_affirmation'].widget.attrs['disabled'] = 'disabled'
def clean(self):
from django.core.exceptions import ValidationError
cleaned_data = super(ApplicationForm, self).clean()
if not self.admin:
applicant_interest_stmt = cleaned_data.get('applicant_interest_stmt')
applicant_affirmation = cleaned_data.get('applicant_affirmation')
if not applicant_interest_stmt:
msg = u'Please provide an interest statement.'
self._errors["applicant_interest_stmt"] = self.error_class([msg])
if not applicant_affirmation:
msg = u'Please check the affirmation checkbox.'
self._errors["applicant_affirmation"] = self.error_class([msg])
return cleaned_data
Upvotes: 1