从函数调用(Django FormView)中提升 Http404 的替代方案?

Alternative to raising Http404 from within a function call, (Django FormView)?

我有一个 FormView,它在模板中呈现一个 ModelForm。该表单包括基于动态查询集的 ModelChoiceField,该查询集在初始化表单时传入 kwargs(请参阅下面视图的完整代码)

 def get_form_kwargs(self, **kwargs):
    """ Provides keyword arguemnt """

    kwargs = super(NameofView, self).get_form_kwargs()

    queryset = self.my_custom_method(self.param1, self.param2)
    kwargs.update({"queryset": queryset})

    return kwargs

此查询集由初始数据库查询使用会话中的值确定,并进一步过滤。在到达上述方法之前,有很多方法在起作用,因此在 request.POST 和 request.GET.

中形成相同的查询集

具体我调用一个方法:

 def get_initial_queryset(self, session_variable1, session_variable2):
     
    initial_queryset = Model.objects.filter(
        attr1=session_variable1
    ).filter(
        attr2__gte=session_variable2)
    
    if not initial_queryset:
        raise Http404("Sorry, none available")
    return initial_queryset

我正在考虑初始查询 returns 没有结果的情况。接下来的方法会报错,最终表单无法渲染,那将是一场灾难!!

因此,我需要以某种方式打破流程,而不是呈现一条类似于 'Sorry nothing was found'.

的消息

如您所见,我目前有 if not initial_queryset: raise Http404() 但我对这个解决方案不满意,因为从技术上讲它不是 'page not found' 并且需要针对此场景的自定义消息。

我更愿意将用户重定向到另一个视图并呈现一条消息,其中包含链接以返回编辑他们的搜索(例如。)

我已经尝试返回 HttpResponseRedirect(),但这只是将 Response 对象分配给调用该函数的变量!

有没有更好的方法来实现这个目标?

class NameofView(FormView):


model = Model
template_name = "app/template.html"
form_class = RefineSelectionForm

def get_initial_queryset(self, session_variable1, session_variable2):
    initial_queryset = Model.objects.filter(
        attr1=session_var1
    ).filter(
        attr2__gte=session_var2)
    if not initial_queryset:
        raise Http404("Sorry, none available")
    return initial_queryset

def refine_queryset1(self, session_var1, session_var2, session_var3):
    initial_queryset = self.get_initial_queryset(session_var1, session_var2)
    refined_qs1 = initial_queryset.filter(session_var1__gte=session_var1)[:3]
    return refined_qs1

def refine_queryset2(self, self, session_var1, session_var2, session_var3):
    initial_queryset = self.get_intitial_queryset(session_var1, session_var2)
    refined_qs2 = initial_queryset.filter(attr__lt=date).order_by("-date")[:3]
    return refined_qs2

def my_custom_method(self, param1, param2):
    """Creates the queryset that will be used by the ModelChoiceField
    in the Form"""

    # Merge both queries
    queryset = param1 | param2
    return queryset

def get_initial(self):
    # Retrieve values from the session
    session_variable1 = self.request.session["session_variable1"]
    self.session_variable2 = self.request.session["session_variable2"]
    self.session_variable3 = self.request.session["session_variable3"]

    ..comparisons etc...

    if condition:
        initial_data = initial_data1
    else:
        initial_data = initial_data2

    initial = super(NameofView, self).get_initial()
    initial.update({"formfield": initial_data})
    return initial

def get_form_kwargs(self, **kwargs):
    kwargs = super(NameofView, self).get_form_kwargs()
    queryset = self.my_custom_method(self.param1, self.param2)
    kwargs.update({"queryset": queryset})
    return kwargs

def get_context_data(self, **kwargs):
    context = super(NameofView, self).get_context_data(**kwargs)       
    queryobject = Model.objects.filter(pk=self.session_variable1)
    context["some_data"] = self.session_variable2
    context["some_object"] = queryobject
    return context

def form_valid(self, form):
    ...code...
    return redirect("named_path", args)

我会覆盖 get 函数来执行基本验证,甚至在进入表单逻辑之前。

from django.shortcuts import render

def get(self, request, *args, **kwargs)
    if not self.get_available_trips().exists():
        return render(request, "some_unavailable_template", context={"message": "your message"})
    return super().get(request, *args, **kwargs)

如您所知,重定向不允许您自定义消息。如果您设置了重定向,则可以重定向到另一个视图,该视图通过相同的逻辑来确定行程不可用的原因,然后显示一条消息。您可能可以将一些常用函数提取到视图混合中。