具有自定义验证的 Django FormSetView

Django FormSetView with custom validation

我正在使用 django-extra-views 中的 ModelFormSetView class 创建连接到 Worker 的所有 WorkerStatus 条目的表单集视图。我还想在表单集上使用自定义验证,所以我在视图中定义了自己的 formset_classform_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)
  1. 您更改了参数的顺序。如果您查看 BaseModelFormset 的代码,第一个参数是数据。这意味着如果有人调用 WorkerStatusFormSet(data, ...)
  2. ,数据可能会被错误地分配给查询集
  3. 您没有对 queryset 做任何事情或将其传递给 super(),因此它丢失了。