Django:在 Mixins Class 视图中验证受限制的外键形式

Django: validation of restricted Foreign keys forms in Mixins Class views

上下文:我如何处理 GET

上的外键限制

我在验证这个 form 时遇到了一些问题:

class RecordConsultationForm(forms.ModelForm):
    class Meta:
        model = Consultation
        fields = ["fk_type", "fk_client", "duration", "date"]

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        super(RecordConsultationForm, self).__init__(*args, **kwargs)
        self.fields['fk_client'].queryset = Client.objects.filter(fk_owner=self.user) # <=====HERE

queryset 将可用的 客户端 限制为 用户 。非常有效,我只需将以下内容添加到 get_context_data()

@method_decorator(login_required, name='dispatch')
class BrowseConsultations(BrowseAndCreate):
    template_name = "console/browse_consultations.html"
    model = Consultation
    form_class = RecordConsultationForm
    success_url = 'browse_consultations'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['form'] = self.form_class(user = self.request.user)  #<=====HERE
        return context

    def post(self, request): 
        form = self.form_class(user = self.request.user) #<=====HERE
        return super().post(request)

BrowseConsultations

上的表单验证

尽管我在 get_context_data()post() 中添加了内容,但 POST 上的表单数据似乎无效,就好像用户是 None(看起来是这样):

Invalid fk_client: Select a valid choice. 2 is not one of the available choices.

也许 get_context_data() 不是设置用户的正确位置?有什么办法可以调整 post() 中的 形式 吗?这是正确的方法吗?

其他详细信息

BrowseAndCreate BrowseConsultations 继承自是我创建的 Mixing class 来处理常见的订购任务和消息。这是其中的一部分:

@method_decorator(login_required, name='dispatch')
class BrowseAndCreate(CreateView, TemplateView):
    """display a bunch of items from a model and the form to create new instances"""

    def post(self, request):
        super().post(request)
        return redirect(self.success_url)

    def form_valid(self, form):
        super().form_valid(form)
        messages.add_message(self.request, messages.SUCCESS,
                             "Recorded in {}".format(self.object.status))

    def form_invalid(self, form):
        for e in form.errors.items():
            messages.add_message(self.request, messages.WARNING,
                                 "Invalid {}: {}".format(e[0], e[1][0]))

环境

首先,CreateView(您的 BrowseAndCreate 继承自)在 post 方法中处理表单验证,它在成功时调用 form_valid form_invalid 失败。这两种方法都应该 return 一个 HTTP 响应。

此外,您覆盖的 FormMixin 中的 get_context_data 已经负责获取表单数据。

如果您需要在您的表单中使用 user,您可以在您的表单中添加:

class RecordConsultationForm(forms.Form):

    def __init__(self, user, *args, **kwargs):
        self.user = user
        super().__init__(*args, **kwargs)

在您看来:

class BrowseConsultations(BrowseAndCreate):

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs