我创建了一个自定义验证错误,在提取基于类的视图之前,它工作得很好。出于某种原因,每当出现错误时,错误只是空白,例如[{}]
验证错误逻辑:
class BaseFormSetValidation(BaseModelFormSet):
def clean(self):
super().clean()
days = ['day_1', 'day_2', 'day_3', 'day_4', 'day_5', 'day_6', 'day_7']
for form in self.forms:
for day in days:
current_day = form.cleaned_data.get(day)
if current_day is not None and current_day > 24:
raise ValidationError([{day: ["Submitted hours per day cannot exceed 24 hours"]}])
class DivErrorList(ErrorList):
def __str__(self):
return self.as_divs()
def as_divs(self):
if not self: return ''
return '%s' % ''.join([e for e in self])
TimesheetModelFormSet = modelformset_factory(Timesheet, formset=BaseFormSetValidation, exclude=("year", "week", "project", "user"), extra=0)
TemplateView Class
class TimesheetEditorView(BaseTimesheet, TemplateView):
form_class = TimesheetModelFormSet
template_name = "timesheets/timesheet.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
timesheet = Timesheet.objects.filter(year=context["year"], week=context["week"], user=self.request.user).order_by("project_id")
timesheet_formset = self.form_class(queryset=timesheet, error_class=DivErrorList)
create_timesheet_form = TimesheetModelForm(self.request.user)
context.update(
timesheet=timesheet,
timesheet_formset=timesheet_formset,
create_timesheet_form=create_timesheet_form
)
return context
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
timesheet_formset = self.form_class(request.POST)
if timesheet_formset.is_valid():
messages.info(request, "Weekly timesheet updated", extra_tags='timesheet')
timesheet_formset.save()
success_url = reverse("timesheets:current-week", args=(context["year"], context["week"]))
return HttpResponseRedirect(success_url)
return render(request, "timesheets/timesheet.html", self.get_context_data(**kwargs))
从
继承class BaseTimesheet(object):
...
def get_context_data(self, **kwargs):
context = super(BaseTimesheet, self).get_context_data(**kwargs)
year = kwargs.get("year") or datetime.datetime.now().year
week = kwargs.get("week") or Week.thisweek().week
user = self.request.user
next_year, next_week = calc_next(year, week)
previous_year, previous_week = calc_previous(year, week)
calc_full_week = self.calc_full_week(year, week)
context.update(
week=week,
year=year,
next_week=next_week,
previous_week=previous_week,
next_year=next_year,
previous_year=previous_year,
current_week=calc_full_week
)
return context
以及带有错误处理的模板:
{% for row in timesheet_formset %}
{% if row.errors %}
<div class="col-lg-10 offset-lg-1 text-center">
<div class="alert alert-warning alert-dismissible fade show">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
Error on project {{ row.instance.project }}
{% endif %}
{% for field in row %}
{% if field.errors %}
{% for error in field.errors %}
<p>{{ field.label }} - {{ error }}</p>
{% endfor %}
{% endif %}
{% endfor %}
{% if row.errors %}
</div>
</div>
{% endif %}
{% endfor %}
{% if timesheet_formset.non_form_errors %}
<div class="col-lg-10 offset-lg-1 text-center">
<div class="alert alert-warning alert-dismissible fade show">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
{{ timesheet_formset.non_form_errors }}
</div>
</div>
{% endif %}
我需要在其他地方传递error_class=DivErrorList
吗?现在,每当发生错误时,表单就可以说是“重置”
这是TimesheetEditorView
重构之前的样子,错误可以在模板中正确输出。逻辑没有发生实际的“改变”-我试图做的就是重构代码,这样我的观点就不会那么“浓厚”
@method_decorator(login_required, name='dispatch')
class TimesheetEditorView(View):
form_class = TimesheetModelFormSet
def get(self, request, *args, **kwargs):
year = kwargs.get("year") or datetime.datetime.now().year
week = kwargs.get("week") or Week.thisweek().week
user = request.user
if invalid_week(week, year):
raise Http404("Invalid week / year")
next_year, next_week = calc_next(year, week)
previous_year, previous_week = calc_previous(year, week)
calc_full_week = self.calc_full_week(year, week)
timesheet = Timesheet.objects.filter(year=year, week=week, user=user).order_by("project_id") # only show timesheet rows that belongs to logged in user
timesheet_formset = self.form_class(queryset=timesheet)
create_timesheet_form = TimesheetModelForm(user)
context = {
"create_timesheet_form": create_timesheet_form,
"timesheet_formset": timesheet_formset,
"week": week,
"year": year,
"next_week": next_week,
"next_year": next_year,
"previous_week": previous_week,
"previous_year": previous_year,
"current_week": calc_full_week,
}
return render(request, "timesheets/timesheet.html", context)
def post(self, request, *args, **kwargs):
year = kwargs.get("year") or datetime.datetime.now().year
week = kwargs.get("week") or Week.thisweek().week
if invalid_week(week, year):
raise Http404("Invalid week / year")
next_year, next_week = calc_next(year, week)
previous_year, previous_week = calc_previous(year, week)
timesheet_formset = self.form_class(request.POST, error_class=DivErrorList)
if timesheet_formset.is_valid():
messages.info(request, "Weekly timesheet updated", extra_tags='timesheet')
timesheet_formset.save()
success_url = reverse("timesheets:current-week", args=(year, week))
return HttpResponseRedirect(success_url)
create_timesheet_form = TimesheetModelForm(request.user)
context = {
"create_timesheet_form": create_timesheet_form,
"timesheet_formset": timesheet_formset,
"week": week,
"year": year,
"next_week": next_week,
"next_year": next_year,
"previous_week": previous_week,
"previous_year": previous_year,
}
return render(request, "timesheets/timesheet.html", context)
答案 0 :(得分:1)
问题是您没有将表格交给:
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
timesheet_formset = self.form_class(request.POST)
if timesheet_formset.is_valid():
messages.info(request, "Weekly timesheet updated", extra_tags='timesheet')
timesheet_formset.save()
success_url = reverse("timesheets:current-week", args=(context["year"], context["week"]))
return HttpResponseRedirect(success_url)
return render(request, "timesheets/timesheet.html", self.get_context_data(**kwargs))
无需使用相同的kwarg调用self.get_context_data(**kwargs)
。而且您必须像在“原始”视图中一样交出timesheet_formset
和create_timesheet_form
。
这将导致如下结果:
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
timesheet_formset = self.form_class(request.POST)
if timesheet_formset.is_valid():
messages.info(request, "Weekly timesheet updated", extra_tags='timesheet')
timesheet_formset.save()
success_url = reverse("timesheets:current-week", args=(context["year"], context["week"]))
return HttpResponseRedirect(success_url)
context['timesheet_formset'] = timesheet_formset
create_timesheet_form = TimesheetModelForm(request.user)
context['create_timesheet_form '] = create_timesheet_form
return render(request, "timesheets/timesheet.html", )
您必须测试是否同时需要timesheet_formset
和create_timesheet_form
。