具有自定义验证的 Django FormSetView
Django FormSetView with custom validation
我正在使用 django-extra-views
中的 ModelFormSetView
class 创建连接到 Worker
的所有 WorkerStatus
条目的表单集视图。我还想在表单集上使用自定义验证,所以我在视图中定义了自己的 formset_class
和 form_class
。这是视图定义:
class WorkerStatusUpdateView(ModelFormSetView):
model = WorkerStatusEntry
formset_class = WorkerStatusFormSet
form_class = WorkerStatusForm
template_name = 'staff/workers/worker_status_update.tmpl'
can_delete = True
can_order = False
fields = ['status', 'start_date']
def dispatch(self, request, *args, **kwargs):
self.worker = Worker.objects.get(pk=self.kwargs['worker_pk'])
return super(WorkerStatusUpdateView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, *args, **kwargs):
ctx = super(WorkerStatusUpdateView, self).get_context_data(*args, **kwargs)
ctx['worker'] = self.worker
return ctx
def get_queryset(self, *args, **kwargs):
return self.worker.statuses.all()
...这里分别是form和formset的定义:
class WorkerStatusForm(forms.ModelForm):
class Meta:
model = WorkerStatusEntry
fields = ['status', 'start_date']
class WorkerStatusFormSet(BaseModelFormSet):
class Meta:
model = WorkerStatusEntry
def __init__(self, queryset, *args, **kwargs):
super(WorkerStatusFormSet, self).__init__(*args, **kwargs)
def clean(self):
print "Cleaning"
这会生成一个页面,其中数据库中的每个 WorkerStatusEntry
都显示在表单集中,而与 get_queryset()
无关。你会注意到的一件事是 WorkerStatusFormSet.__init__
有一个 queryset
参数:我把它放在那里是因为有一个 queryset
参数从 ModelFormSetView
传递给它,但我不不知道该怎么办。
另一件需要注意的事情:如果我从视图定义中取出 formset_class = WorkerStatusFormSet
,正确的查询集会出现在表单集中。但是我需要使用我自己的表单集 class 来验证整个表单集。除非有别的办法?
问题出在您的 WorkerStatusFormSet.__init__
方法上。查看 BaseModelFormSet
的代码,__init__
方法已经采用了一个查询集参数。由于除了调用 super()
之外,您没有在 __init__
方法中执行任何操作,因此最简单的解决方法是将其删除。
像您所做的那样更改 __init__
方法的签名不是一个好主意,原因有二
def __init__(self, queryset, *args, **kwargs):
super(WorkerStatusFormSet, self).__init__(*args, **kwargs)
- 您更改了参数的顺序。如果您查看
BaseModelFormset
的代码,第一个参数是数据。这意味着如果有人调用 WorkerStatusFormSet(data, ...) ,数据可能会被错误地分配给查询集
- 您没有对
queryset
做任何事情或将其传递给 super()
,因此它丢失了。
我正在使用 django-extra-views
中的 ModelFormSetView
class 创建连接到 Worker
的所有 WorkerStatus
条目的表单集视图。我还想在表单集上使用自定义验证,所以我在视图中定义了自己的 formset_class
和 form_class
。这是视图定义:
class WorkerStatusUpdateView(ModelFormSetView):
model = WorkerStatusEntry
formset_class = WorkerStatusFormSet
form_class = WorkerStatusForm
template_name = 'staff/workers/worker_status_update.tmpl'
can_delete = True
can_order = False
fields = ['status', 'start_date']
def dispatch(self, request, *args, **kwargs):
self.worker = Worker.objects.get(pk=self.kwargs['worker_pk'])
return super(WorkerStatusUpdateView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, *args, **kwargs):
ctx = super(WorkerStatusUpdateView, self).get_context_data(*args, **kwargs)
ctx['worker'] = self.worker
return ctx
def get_queryset(self, *args, **kwargs):
return self.worker.statuses.all()
...这里分别是form和formset的定义:
class WorkerStatusForm(forms.ModelForm):
class Meta:
model = WorkerStatusEntry
fields = ['status', 'start_date']
class WorkerStatusFormSet(BaseModelFormSet):
class Meta:
model = WorkerStatusEntry
def __init__(self, queryset, *args, **kwargs):
super(WorkerStatusFormSet, self).__init__(*args, **kwargs)
def clean(self):
print "Cleaning"
这会生成一个页面,其中数据库中的每个 WorkerStatusEntry
都显示在表单集中,而与 get_queryset()
无关。你会注意到的一件事是 WorkerStatusFormSet.__init__
有一个 queryset
参数:我把它放在那里是因为有一个 queryset
参数从 ModelFormSetView
传递给它,但我不不知道该怎么办。
另一件需要注意的事情:如果我从视图定义中取出 formset_class = WorkerStatusFormSet
,正确的查询集会出现在表单集中。但是我需要使用我自己的表单集 class 来验证整个表单集。除非有别的办法?
问题出在您的 WorkerStatusFormSet.__init__
方法上。查看 BaseModelFormSet
的代码,__init__
方法已经采用了一个查询集参数。由于除了调用 super()
之外,您没有在 __init__
方法中执行任何操作,因此最简单的解决方法是将其删除。
像您所做的那样更改 __init__
方法的签名不是一个好主意,原因有二
def __init__(self, queryset, *args, **kwargs):
super(WorkerStatusFormSet, self).__init__(*args, **kwargs)
- 您更改了参数的顺序。如果您查看
BaseModelFormset
的代码,第一个参数是数据。这意味着如果有人调用 WorkerStatusFormSet(data, ...) ,数据可能会被错误地分配给查询集
- 您没有对
queryset
做任何事情或将其传递给super()
,因此它丢失了。