问题
I am trying to add a validator to django model form such that if specific value is selected then other field in the form should be entered if not entered it should give a validation error
in the below form if the user selects "Project Support Activities" from the activity_name drop down then the project id field should be mandatory
Django Form
class ActivityTrackerModelForm(forms.ModelForm):
date = forms.DateField(label='', widget=forms.DateInput(attrs={
"placeholder": "Select Date", 'id': 'datepicker', 'class': 'form-control w-100', 'autocomplete': 'off'}))
activity_name = forms.ModelChoiceField(queryset=activity.objects.all().order_by(
'activity_name'), label='', empty_label="Select Activity", widget=forms.Select(attrs={'class': 'form-control w-100'}))
system_name = forms.ModelChoiceField(queryset=system.objects.all().order_by('system_name'), label='', empty_label="Select System", widget=forms.Select(attrs={
'class': 'form-control w-100'}))
client_name = forms.ModelChoiceField(queryset=client.objects.all().order_by(
'client_name'), label='', empty_label="Select Client", widget=forms.Select(attrs={
'class': 'form-control w-100'}))
hour_choice = [('', 'Choose Hours'), (0, 0), (1, 1), (2, 2),(3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8)]
hours = forms.ChoiceField(label='', choices=hour_choice, widget=forms.Select(
attrs={'class': 'form-control w-100'}))
min_choice = [('', 'Choose Mins'), (0, 0), (15, 15), (30, 30), (45, 45)]
mins = forms.ChoiceField(label='', choices=min_choice, widget=forms.Select(attrs={'class': 'form-control w-100'}))
no_of_records = forms.IntegerField(label='', required=False, widget=forms.NumberInput(
attrs={"placeholder": "Enter no. of Records", 'class': 'form-control w-100', 'autocomplete': 'off'}))
project_id = forms.CharField(label='', required=False, widget=forms.TextInput(
attrs={"placeholder": "Project ID", 'class': 'form-control w-100'}))
user_comments = forms.CharField(
label='',
required=False,
widget=forms.Textarea(
attrs={
"placeholder": "Enter Your Comments Here...",
'rows': 6,
'class': 'form-control w-100',
'autocomplete': 'off'
}
)
)
class Meta:
model = activity_tracker
fields = ['date', 'activity_name', 'system_name', 'client_name',
'hours', 'mins', 'no_of_records', 'project_id', 'user_comments']
def clean(self):
cleaned_data = super(ActivityTrackerModelForm, self).clean()
activity = cleaned_data.get('activity_name')
project_1 = cleaned_data.get('project_id')
if re.search("^Project.*Activities$", str(activity)) or project_1 is None:
print('pass') # prints to console this is working
raise forms.ValidationError('Please Add in Project ID')#raise form error this is not working
View :
def MyTask(request):
if request.method == 'POST':
form = ActivityTrackerModelForm(request.POST or None)
if form.is_valid():
obj = form.save(commit=False)
obj.user_name = request.user
obj.approver = tascaty_user.objects.get(
username=request.user).approver
if request.user.is_team_lead:
obj.status = activity_status.objects.get(pk=3)
obj.save()
return redirect('mytask')
queryset1_PA = activity_tracker.objects.filter(
user_name=request.user).filter(status__in=[1, 2, 4]).order_by('-id')
queryset1_AP = activity_tracker.objects.filter(
user_name=request.user).filter(status=3).order_by('-date')
paginator_RA = Paginator(queryset1_AP, 10)
paginator_PA = Paginator(queryset1_PA, 10)
page = request.GET.get('page')
context = {
'title': 'TasCaty|My Task',
'activity_form': ActivityTrackerModelForm(),
'post_page_RA': paginator_RA.get_page(page),
'post_page_PA': paginator_PA.get_page(page),
}
return render(request, "tascaty/mytask.html", context)
回答1:
Raising the error is working fine. But you always redirect away, even if the form is not valid, so the error will never be displayed.
You should only redirect when is_valid is True, otherwise you should redisplay the form. That means passing the invalid form back to the context - so you should only create a new one when method is not POST. So:
if request.method == 'POST':
form = ActivityTrackerModelForm(request.POST or None)
if form.is_valid():
...
obj.save()
return redirect('mytask') # indented here
else:
ActivityTrackerModelForm() # added this block, note it's aligned with the first if
...
context = {
...
'activity_form': form, # pass the existing form here
...
}
return render(request, "tascaty/mytask.html", context)
回答2:
Changed MY View as mentioned by @Daniel Roseman and changed form validator
View
if request.method == 'POST':
form = ActivityTrackerModelForm(request.POST or None)
if form.is_valid():
...
obj.save()
return redirect('mytask') # indented here
else:
ActivityTrackerModelForm() # added this block, note it's aligned with the first if
...
context = {
...
'activity_form': form, # pass the existing form here
...
}
return render(request, "tascaty/mytask.html", context)
Form Validator
def clean(self):
cleaned_data = super(ActivityTrackerModelForm, self).clean()
activity = cleaned_data.get('activity_name')
project_1 = cleaned_data.get('project_id')
if re.search("^Project.*Activities$", str(activity)) and project_1 == "":
self.add_error('project_id', "Please Add Project ID")
return cleaned_data
来源:https://stackoverflow.com/questions/55650306/django-raise-forms-validationerror-not-working