Model form is crashing on a foreign key in django - python

So I'm trying to create a new feed within the Admin page and its
crashing with the error IntegrityError: lifestream_feed.lifestream_id
may not be NULL, form['lifestream'] is set but
form.instance.lifestream is not.
form.fields even shows that lifestream is a django.forms.models.ModelChoiceField
Here is the code:
class FeedCreationForm(forms.ModelForm):
class Meta:
model = Feed
exclude = ['name', 'domain', 'fetchable']
def parse_feed(self, feed_url):
feed = feedparser.parse(feed_url)
# Does the feed have errors
if feed['bozo']:
if feed['feed'].has_key("links"):
for link in feed['feed']['links']:
if link["type"] == "application/rss+xml":
feed = self.parse_feed(link['href'])
if not feed['bozo']:
return feed
else:
return feed
return None
def clean(self):
"""
Checks to make sure a feed url is valid and gets the feed
title
and domain.
"""
feed_url = self.cleaned_data.get('url')
if not feed_url:
# Feed url was not validated by the field validator
return
feed = self.parse_feed(feed_url)
if feed:
feed_url = feed['url']
self.cleaned_data['url'] = feed_url
else:
# the feed was not parsed correctly.
import logging
self._errors['url'] = ErrorList(["This is not a valid
feed: %s" % feed['bozo_exception']])
logging.error(feed['bozo_exception'])
# This field is no longer valid. Remove from cleaned_data
del self.cleaned_data['url']
return
# Check if the feed has a title field
feed_info = feed.get('feed')
if not feed_info.get('title'):
self._errors['url'] = ErrorList(["This is not a valid
feed: The feed is empty"])
# This field is no longer valid. Remove from cleaned_data
del self.cleaned_data['url']
return
self.cleaned_data['name'] = feed_info['title']
self.instance.name = self.cleaned_data['name']
self.cleaned_data['domain'] = get_url_domain(feed_url)
self.instance.domain = self.cleaned_data['domain']
return self.cleaned_data
class FeedAdmin(admin.ModelAdmin):
list_display = ('name', 'lifestream', 'domain', 'fetchable')
list_filter = ('domain', 'lifestream')
actions = ['make_fetchable', 'make_unfetchable']
add_form = FeedCreationForm
model = Feed
def make_unfetchable(self, request, queryset):
queryset.update(fetchable=False)
make_unfetchable.short_description = _(u"Mark as unfetchable")
def make_fetchable(self, request, queryset):
queryset.update(fetchable=True)
make_fetchable.short_description = _(u"Mark as fetchable")
def add_view(self, request):
if not self.has_change_permission(request):
raise PermissionDenied
if request.method == 'POST':
form = self.add_form(request.POST)
if form.is_valid():
new_feed = form.save()
msg = _('The %(name)s "%(obj)s" was added
successfully.') % {'name': 'user', 'obj': new_feed}
self.log_addition(request, new_feed)
if "_addanother" in request.POST:
request.user.message_set.create(message=msg)
return HttpResponseRedirect(request.path)
elif '_popup' in request.REQUEST:
return self.response_add(request, new_feed)
else:
request.user.message_set.create(message=msg + ' '
+ ugettext("You may edit it again below."))
# TODO: use reversed url
return HttpResponseRedirect('../%s/' %
new_feed.id)
else:
form = self.add_form()
return render_to_response('admin/lifestream/feed/
add_form.html', {
'title': _('Add feed'),
'form': form,
'is_popup': '_popup' in request.REQUEST,
'add': True,
'change': False,
'has_add_permission': True,
'has_delete_permission': False,
'has_change_permission': True,
'has_file_field': False,
'has_absolute_url': False,
'auto_populated_fields': (),
'opts': self.model._meta,
'save_as': False,
#'username_help_text': self.model._meta.get_field
('username').help_text,
'root_path': self.admin_site.root_path,
'app_label': self.model._meta.app_label,
}, context_instance=template.RequestContext(request))
def queryset(self, request):
return self.model.objects.feeds()
admin.site.register(Feed, FeedAdmin)
class Lifestream(models.Model):
"""
A lifestream. Lifestreams can be created per user.
"""
site = models.ForeignKey(Site, verbose_name=_(u"site"))
user = models.ForeignKey(User, verbose_name=_(u"user"))
slug = models.SlugField(_("slug"), help_text=_('Slug for use in
urls (Autopopulated from the title).'), blank=True)
title = models.CharField(_("title"), max_length=255)
def __unicode__(self):
return self.title
class FeedManager(models.Manager):
''' Query only normal feeds. '''
def feeds(self):
return super(FeedManager, self).get_query_set()
def fetchable(self):
return self.feeds().filter(fetchable=True)
class Feed(models.Model):
'''A feed for gathering data.'''
lifestream = models.ForeignKey(Lifestream, verbose_name=_
('lifestream'))
name = models.CharField(_("feed name"), max_length=255)
url = models.URLField(_("feed url"), help_text=_("Must be a valid
url."), verify_exists=True, max_length=1000)
domain = models.CharField(_("feed domain"), max_length=255)
fetchable = models.BooleanField(_("fetchable"), default=True)
# The feed plugin name used to process the incoming feed data.
plugin_class_name = models.CharField(_("plugin name"),
max_length=255, null=True, blank=True, choices=getattr(settings,
"PLUGINS", PLUGINS))
objects = FeedManager()
def __unicode__(self):
return self.name
Its not returning the empty returns, its reaching the return self.cleaned_data:
-> return self.cleaned_data
(Pdb) list
85 self.cleaned_data['name'] = feed_info['title']
86 self.instance.name = self.cleaned_data['name']
87 self.cleaned_data['domain'] = get_url_domain(feed_url)
88 self.instance.domain = self.cleaned_data['domain']
89
90 -> return self.cleaned_data
91
92 class FeedAdmin(admin.ModelAdmin):
93 list_display = ('name', 'lifestream', 'domain', 'fetchable')
94 list_filter = ('domain', 'lifestream')
95 actions = ['make_fetchable', 'make_unfetchable']
(Pdb) self.cleaned_data
{'url': u'http://twitter.com/statuses/user_timeline/6166742.rss', 'domain': u'twitter.com', 'lifestream': <Lifestream: Social>, 'name': u'Twitter / sontek', 'plugin_class_name': u'lifestream.plugins.twitter.TwitterPlugin'}

I believe the problem is in your clean() method.
The general clean() method (as opposed to field specific clean methods like clean_domain()) must return the cleaned_data dictionary (minus any fields which do not validate), and you have at least 3 returns in your clean method that do not return anything.
See here

Turns out this is a bug in HEAD of django

Related

Django - NOT NULL constraint failed

I'm currently working on a Django app that will parse the contents of an uploaded log file to the associated database in my Django project. I've managed to get it all running as expected except it won't associate my uploaded data with the model's ForeignKey. I can assign null=True which resolves the integrity error but then of course, it doesn't assign any of the uploaded data to that ForeignKey. Here's the code:
models.py
class Case(models.Model):
case_ref = models.CharField(max_length=8)
oic = models.CharField(max_length=50)
subject = models.CharField(max_length=100)
submitted_date = models.DateTimeField(default=datetime.now, blank=True)
def get_absolute_url(self):
return reverse('case_list', kwargs={'pk': self.pk})
def __str__(self):
return self.case_ref + " " + self.subject
class TeamviewerLogs(models.Model):
case = models.ForeignKey(Case, on_delete=models.DO_NOTHING)
teamviewer_id = models.IntegerField()
teamviewer_name = models.TextField()
connection_start = models.TextField()
connection_end = models.TextField()
local_user = models.TextField()
connection_type = models.TextField()
unique_id = models.TextField()
def get_absolute_url(self):
return reverse('case_list', kwargs={'pk': self.pk})
def __str__(self):
return str(self.teamviewer_id) + " - " + str(self.teamviewer_id)
forms.py
class UploadLog(forms.ModelForm):
file = forms.FileField()
class Meta:
model = TeamviewerLogs
fields = [
'file'
]
views.py
def add_logs(request, pk):
case = get_object_or_404(Case, pk=pk)
if request.method == 'POST':
form = UploadLog(request.POST, request.FILES)
if form.is_valid():
teamviewer = form.save(commit=False)
teamviewer.case = case
log_file = request.FILES['file']
log_file = filter(None, (line.rstrip() for line in log_file))
for lines in log_file:
split = lines.decode('utf-8').split('\t')
teamviewer_id = split[0]
teamviewer_name = split[1]
connection_start = split[2]
connection_end = split[3]
local_user = split[4]
connection_type = split[5]
unique_id = split[6]
teamviewer = TeamviewerLogs(teamviewer_id=teamviewer_id, teamviewer_name=teamviewer_name,
connection_start=connection_start, connection_end=connection_end,
local_user=local_user, connection_type=connection_type, unique_id=unique_id)
teamviewer.save()
return redirect('tv_log_details', pk=case.pk)
form.save()
else:
form = UploadLog()
return render(request, 'teamviewer/add_logs.html', {'form': form})
But when I click to upload the file I'm hit with:
When it tries to execute teamviewer.save().
I've been trying to resolve this issue for hours and have tried so many different variations of answers from Stackoverflow or previous code I've used that has worked for different models but I've hit a brick wall...hard!
Any help anyone can offer would be greatly appreciated.
Ok, so here's an example of the concept I've suggested in the comments.
I've got a view which passes some data to the a form;
class ListingDetailView(DetailView):
""" Listing detail page """
model = Listing
template_name = 'listing.html'
def get_form_kwargs(self):
"""Return the kwargs for the form"""
kwargs = {}
initial = {
'listing': self.object,
}
kwargs['initial'] = initial
return kwargs
def get_form(self):
form = ApplicationSignupForm(
**self.get_form_kwargs()
)
return form
def get_context_data(self, **kwargs):
""" Add our form to the context """
context = super().get_context_data(**kwargs)
context['form'] = self.get_form()
return context
The form then makes use of that initial data and sets the field it relates to as hidden. I don't validate this data, but I'll try to show how you might do that;
class ApplicationSignupForm(forms.ModelForm):
class Meta:
""" Setup the form """
fields = (
'listing',
...
)
model = Application
widgets = {
'listing': forms.HiddenInput()
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
initial_data = kwargs['initial']
self.listing = initial_data.get('listing')
def clean(self):
"""
Custom form cleaning
"""
cleaned_data = super().clean()
listing = cleaned_data.get('listing')
if listing != self.listing:
self.add_error('listing', "You can't modify this value")
return cleaned_data

Error when inserting into database Django

I have a new problem, it is when I insert in the database the news, it adds but without the region. How can I insert the comment with the correct region?
Here is my view :
def index_region(request,region):
try:
actuCommentaire = Actu.objects.get(region=region)
except ObjectDoesNotExist:
actuTempo = Actu(region=region)
actuCommentaire = actuTempo.commentaire
form = UpdateActu(request.POST or None, instance=actuCommentaire)
if form.is_valid():
form.save()
return redirect('index.html')
Here is my model "Actu" :
class Actu(models.Model):
commentaire = models.TextField(max_length=200, null=True)
region = models.CharField(max_length=30, null=True)
def __str__(self):
return self.region
Here is my form :
class UpdateActu(forms.ModelForm):
class Meta:
model = models.Actu
fields = ['commentaire']
widgets = {
'commentaire': forms.Textarea(attrs={'class': 'form-control', 'id': 'exampleTextarea', 'rows': '2'})
}
Here is the result when inserting into the database :
enter image description here
I found how to solve the problem.
Here is my new view :
try:
actuCommentaire = Actu.objects.get(region=region)
except ObjectDoesNotExist:
actuTempo = Actu(region=region)
actuCommentaire = actuTempo.commentaire
form = UpdateActu(request.POST or None, instance=actuCommentaire)
if form.is_valid():
if Actu.objects.filter(region=region).count() == 0:
formActu = Actu(commentaire=request.POST['commentaire'], region=region)
formActu.save()
else:
form.save()
return redirect('index.html')

Creating a multi-step form using a ModelForm in Django

I am attempting to create a multi-step ModelForm using a library called FormWizard. However, I am having difficulty getting the results I want.
Work Flow
User clicks on create patient link
User opens patient form
User inserts patient data
User submits form
if form is invalid:
redisplay form with error
if form is valid:
move to next form
enter symptom data
submit form
if form is invalid:
redisplay form with error
if form is valid:
move to next form
enter disease data
submit form
if form is invalid:
redisplay form with error
if form is valid:
User is redirected to general form that has patient + symptom + disease information.
View that will create the multi-step ModelForm
class ConsultationCreate(SessionWizardView):
instance = None
def get_form_instance(self, step):
if self.instance is None:
self.instance = Patient
return self.instance
template_ = 'data/multi_form.html'
def done(self, form_list, **kwargs):
self.instance.save()
def process_form_data(form_list):
form_data = [form.cleaned_data for form in form_list]
logr.debug(form_data[0]['NIS'])
logr.debug(form_data[1]['identity'])
logr.debug(form_data[2]['identity'])
return form_data
This is the error it produces:
ValidationError at /patient/create
['ManagementForm data is missing or has been tampered.']
The code
urls.py
from django.conf.urls import url
from data.views import IdentityList, IdentityCreate, IdentitySpecific, ConsultationCreate, MultiStep
from data.forms import SymptomForm, DiseaseForm, IdentityForm
urlpatterns = [
url(r'^patient/$', IdentityList.as_view(), name = 'data_patient_list'),
url(r'^patient/create$', ConsultationCreate.as_view([IdentityForm, SymptomForm, DiseaseForm]), name = 'data_patient_create'),
]
models.py
from django.db import models
from django.utils import timezone
from django.shortcuts import reverse
import datetime
Creates Patient database
class Patient(models.Model):
NIS =models.CharField(max_length = 200, primary_key = True)
timestamp = models.DateTimeField(auto_now = True)
first_name = models.CharField(max_length = 80, null = True)
last_name = models.CharField(max_length = 80, null = True )
contact = models.CharField(max_length = 15, null = True)
location = models.CharField(max_length = 100, blank = True)
email_address = models.EmailField()
CHOOSE = 'The patient is'
MALE = 'M'
FEMALE = 'F'
personGender = ((CHOOSE,'The patient is'),(MALE, 'Male'),(FEMALE,'Female'),)
gender = models.CharField(max_length=2,choices=personGender,default=CHOOSE)
born = models.DateField(auto_now = False, auto_now_add = False, blank = True, null = True)
Creates Symptom database
class Symptom(models.Model):
identity = models.CharField('Name of symptom', max_length = 80, default = '')
description = models.TextField(max_length = 1000, default = '')
patient = models.ManyToManyField(Patient, through = 'Consultation')
def __str__(self):
return '%s' % ( self.identity )
Creates Disease database
class Disease(models.Model):
identity = models.CharField('Name of disease', max_length = 80, default = '')
description = models.TextField(max_length = 5000, default = '')
symptom = models.ManyToManyField(Symptom)
def __str__(self):
return '%s' % ( self.identity )
Consultation model is the intermediate model
class Consultation(models.Model):
patient_identity = models.ForeignKey(Patient)
patient_condition = models.ForeignKey(Symptom)
patient_disease = models.ForeignKey(Disease)
patient_treatment = models.ForeignKey(Treatment)
consultation_date_and_time = models.DateTimeField('visitation date and time', auto_now = False, auto_now_add = False, blank = True, null = True)
# Use get_absolute_url to access single page model objects that possess a Canonical Uniform resource locator
def get_absolute_url(self):
return reverse('data_patient_detail', kwargs={'pk':self.pk})
views.py
from data.models import Treatment, Symptom, Disease, Consultation, Patient
from django.shortcuts import get_object_or_404, render, redirect, render_to_response
from django.views.generic import View
from data.forms import IdentityForm
from formtools.wizard.views import SessionWizardView
Class based view for patient list
class IdentityList(View):
template_ = 'data/patient_list.html'
def get(self, request):
patient_list = Consultation.objects.all()
return render(request, self.template_, {'patient_list':patient_list})
Class based view for patient detail
class IdentitySpecific(View):
model = Consultation
template_ = 'data/patient_detail.html'
def get(self, request, pk):
patient_consult = Consultation.objects.filter(pk=pk)
return render(request, self.template_, {'patient_consult':patient_consult})
Class based view for multi-step modelform
class ConsultationCreate(SessionWizardView):
instance = None
def get_form_instance(self, step):
if self.instance is None:
self.instance = Patient
return self.instance
template_ = 'data/multi_form.html'
def done(self, form_list, **kwargs):
self.instance.save()
Function process_form_data using to process form data in
ConsultationCreate view
def process_form_data(form_list):
form_data = [form.cleaned_data for form in form_list]
logr.debug(form_data[0]['NIS'])
logr.debug(form_data[1]['identity'])
logr.debug(form_data[2]['identity'])
return form_data

Django: Setting values of certain attributes in the database using views?

I have a form in my application which has a hidden form field, the value of which I want to set in my corresponding view after submitting the form.
forms.py
class EvangelizedForm(forms.ModelForm):
first_name = forms.CharField(help_text="First Name")
last_name = forms.CharField(help_text="Last Name")
email = forms.CharField(help_text="Email ID")
mobile_no = forms.CharField(help_text="Mobile number")
twitter_url = forms.CharField(help_text="Twitter URL")
twitter_followers = forms.CharField(widget = forms.HiddenInput()) #Hidden form field
class Meta:
model = Evangelized
fields = ('first_name','last_name', 'twitter_url', 'email', 'mobile_no')
models.py
class Evangelized(models.Model):
first_name = models.CharField(max_length=128)
last_name = models.CharField(max_length=128)
email = models.EmailField()
mobile_no = models.CharField(unique=True, max_length = 10, validators=[RegexValidator(regex='^\w{10}$', message='Mobile number should be strictly of 10 digits.')])
twitter_url = models.CharField(unique=True, max_length=128)
twitter_followers = models.CharField(max_length = 128)
views.py
def fillform(request):
follower_count = '250'
if request.method == 'POST':
form = EvangelizedForm(request.POST)
if form.is_valid():
form.fields['twitter_followers'] = follower_count
form.save(commit=True)
return index(request)
else:
form.errors
else:
#form = EvangelizedForm()
if request.user.is_authenticated():
form = EvangelizedForm(initial={'first_name': request.user.first_name,
'twitter_url': 'https://twitter.com/' + request.user.username,
'last_name': request.user.last_name})
else:
form = EvangelizedForm()
context = RequestContext(request,
{'request': request,
'user': request.user, 'form':form})
#return render(request, 'rango/fillform.html', {'form': form, 'context_instance':context})
return render_to_response('rango/fillform.html',
context_instance=context)
Basically, I'm trying to set the value of twitter_followers (which is a hidden form field in forms.py) in my index view, by:
follower_count = '250'
..
..
form.fields['twitter_followers'] = follower_count
By doing this, I'm expecting the value of 'twitter_followers' in the database after submitting the form to be '250'. However, this approach doesn't seem to be working.
What's the right way to set values to certain attributes in the database manually using views?
You need to set it on the model instance, which is the result of form.save. That's the main reason for the commit argument in the first place.
if form.is_valid()
obj = form.save(commit=True)
obj.twitter_follower = follower_count
obj.save()
You can override the save method of the form, with something like this:
def save(self, *args, **kwargs)
twitter_followers = kwargs.pop('twitter_followers', 0)
self.instance.twitter_followers = twitter_followers
super(Evangelized, self).save(args, kwargs)
And then in the view just have to call in this way:
form.save(twitter_followers=250)

ModelForm __init__ problems

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.
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

Categories