私は次のモデルを持っています:
class Project(models.Model):
title = models.CharField(max_length="100")
pub_date = models.DateField(auto_now_add=True, editable=False)
budget = models.IntegerField()
class Milestone(models.Model):
title = models.CharField(max_length="50")
budget_percentage = models.IntegerField(max_length=2)
project = models.ForeignKey(Project)
プロジェクトの作成フォームに、マイルストーン用のインライン フォームセットを含めました。
プロジェクトが提出されたときに、少なくとも 4 つのマイルストーンが作成され、すべてのマイルストーンの Budget_percentage の合計が 100 になることを検証したい
これは私のフォームです:
class BaseMilestoneProjectFormSet(BaseFormSet):
def clean(self):
if any(self.errors):
# Don't bother validating the forms unless each form is valid on its own
return
if len(self.forms) < REQUIRED_MILESTONES:
raise forms.ValidationError("At least %s milestones need to be created" % REQUIRED_MILESTONES)
# Set initial control variables
# Total percentage of budget to control
total_percentage = 0
# Date to control that milestones are linear, i.e. that second milestone isn't delivered before first
current_control_date = date.min
for i, form in zip(range(len(self.forms)), self.forms):
if i == 0 and form.budget_percentage > MAX_BUDGET_FIRST_MILESTONE:
raise forms.ValidationError("First milestone budget must not exceed %s percentage" % MAX_BUDGET_FIRST_MILESTONE)
elif form.budget_percentage > MAX_BUDGET_MILESTONE:
raise forms.ValidationError("Milestone's budget must not exceed %s percentage" % MAX_BUDGET_MILESTONE)
if form.estimated_delivery_date < current_control_date:
raise forms.ValidationError("Milestones must be linear, check your delivery dates")
# Set control variables for next iteration
current_control_date = form.estimated_delivery_date
total_percentage += form.budget_percentage
if total_percentage != 100:
raise forms.ValidationError("All milestones budget percentage should sum up to 100%")
3 つの空のマイルストーン フォームを含むフォームを送信すると、最初のフォームについては何もしません。ValidationError(...)
raise Exception() で実際に if に入ることを確認しましたが、何も起こらないかのように続行します。
それは私のコードのエラーですか、それとも ValidationError の誤解された概念ですか?
事前に感謝します。
編集:
欠落していたビューコードを追加しています
class DelayedModelFormMixin(ModelFormMixin):
def form_valid(self, form):
self.object = form.save(commit=False)
self.prepare_object_for_save(self.object)
self.object.save()
if hasattr(self.object, "save_m2m"):
self.object.save_m2m()
return super(ModelFormMixin, self).form_valid(form)
def prepare_object_for_save(self, obj):
pass
class ProjectNew(CreateView, DelayedModelFormMixin):
model = Project
success_url = '/projects/project/%(slug)s'
form_class = ProjectForm
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(ProjectNew, self).dispatch(request, *args, **kwargs)
def prepare_object_for_save(self, obj):
obj.owner = self.request.user
# Code for stacked milestones and rewards
context = self.get_context_data()
milestone_form = context['milestone_formset']
reward_form = context['reward_formset']
if milestone_form.is_valid() and reward_form.is_valid():
self.object = form.save()
milestone_form.instance = self.object
milestone_form.save()
reward_form.instance = self.object
reward_form.save()
return HttpResponseRedirect(success_url)
def form_invalid(self, form):
return self.render_to_response(self.get_context_data(form=form))
def get_context_data(self, **kwargs):
context = super(ProjectNew, self).get_context_data(**kwargs)
if self.request.POST:
context['milestone_formset'] = MilestoneFormSet(self.request.POST)
context['reward_formset'] = RewardFormSet(self.request.POST)
else:
context['milestone_formset'] = MilestoneFormSet()
context['reward_formset'] = RewardFormSet()
return context