1

我有一个汽车模型,我想通过相互依赖的 ModelChoiceField 进行过滤:

class Car(models.Model):
    make = models.CharField(max_length=50)
    model = models.CharField(max_length=50)
    platform = models.CharField(max_length=50)

表格.py:

class MakeSelectForm(forms.ModelForm):
    make = forms.ModelChoiceField(queryset=Car.objects.values_list('make',flat=True).distinct())
    class Meta:
        model = Car
        fields = ["make"]

class ModelSelectForm(forms.ModelForm):
    model = forms.ModelChoiceField(queryset=Car.objects.values_list('model',flat=True).distinct())
    class Meta:
        model = Car
        fields = ["make", "model"]

视图.py:

def make_select_view(request):
    form = MakeSelectForm()
    make = None
    if request.method == "POST":
        form = MakeSelectForm(request.POST)
        if form.is_valid():
            make = form.cleaned_data['make']
    return render(request, "reviews/makeselect.html", {"form": form, "make": make})

def model_select_view(request, make):
    form = ModelSelectForm()
    model = None
    if request.method == "POST":
        form = MakeSelectForm(request.POST)
        if form.is_valid():
            model = form.cleaned_data['model']
    return render(request, "reviews/modelselect.html", {"form": form, "model": model})

网址:

urlpatterns = [
    url(r'^$', views.make_select_view, name="make-select"),
    url(r'^(?P<make>\w+)/$', views.model_select_view, name="model-select"),
]

Makeselect.html:

<form action="{% url 'reviews:model-select' make %}" method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Select" />
</form>

现在,我必须在发布时将第一个表单的“make”参数传递给第二个视图,然后使用它来过滤具有该 make 的 Car 实例。但是在这里我通过的是“无”,并得到选择一个有效的选择。该选择不是可用的选择之一。第二种形式的错误。

任何建议或反馈都将受到欢迎并非常感谢。

谢谢你。

4

2 回答 2

1

由于我在评论中发布的片段的格式被弄乱了,所以我在这里写下它作为答案。

def __init__(self, *args, **kwargs):
    self.request = kwargs.pop('request', None)
    super(GameForm, self).__init__(*args, **kwargs)
    if not self.request.user.is_staff:
        self.fields['publisher'].queryset = Publisher.objects.filter(id=self.request.user.id)
于 2017-07-17T12:09:30.097 回答
1

第一点:模型表单用于创建/编辑模型,所以你应该在这里使用普通表单。您的错误来自您的make字段,ModelSelectForm但没有在任何地方设置它的值。此外,ModelChoiceField它是为了检索模型实例,而不是字段的值,所以你真的想要一个ChoiceField这里。

第二点,由于您的目标是显示过滤信息 - 而不是创建或编辑任何内容 - 您应该使用GET查询(实际上就像任何“搜索”功能一样)。

为了使您的第二个表单按预期工作(一旦移植到Form具有单个model字段的普通表单),您需要将make值传递给表单,并在表单__init__()中将model字段选择更新为过滤后的查询集。

此外,由于您将使用GET表单的方法,因此您必须检查表单是否已提交,然后再决定是否使用request.GET数据进行实例化,否则用户将在首次显示之前收到错误消息提交任何东西的机会。这通常可以使用表单提交按钮的名称和值或表单本身的隐藏字段来解决:

形式:

class  ModelSelectForm(forms.Form):
    model = forms.ChoiceField()

    def __init__(self, *args, **kwargs):
        make = kwargs.pop("make", None)
        if not make:
            raise ValueError("expected a 'make' keyword arg")
        super(ModelSelectForm, self).__init__(*args, **kwargs)
        qs = Car.objects.filter(make=make).values_list('model',flat=True).distinct()
        choices = [(value, value) for value in qs]
        self.fields["model"].choices = choices

意见:

def model_select_view(request, make):
    model = None
    if request.GET.get("submitted", None):
        form = ModelSelectForm(request.GET, make=make)
        if form.is_valid():
            model = form.cleaned_data['model']
    else:
        form = ModelSelectForm(make=make)
    context = {"form": form, "model": model, "make: make}
    return render(request, "reviews/modelselect.html", context)

模板:

<form action="{% url 'reviews:model-select' make %}" method="GET">
    {% csrf_token %}
    <input type="hidden" name="submitted" value="1" />
    {{ form.as_p }}
    <input type="submit" value="Select" />
</form>

wrt /您关于“将'make'传递给第二个视图”的问题:您的代码片段中没有任何地方可以将用户引导到model-select视图,但我假设您想要的是用户在成功选择后被重定向到它“制作”在第一个视图中。如果是,您的第一个视图的代码应该处理成功提交表单的情况,即:

def make_select_view(request):
    if request.GET.get("submitted", None):
        form = MakeSelectForm(request.GET)
        if form.is_valid():
            make = form.cleaned_data['make']
            # send the user to the model selection view
            return redirect("reviews:model-select", make=make)

    else:
        form = MakeSelectForm()
    context = {"form": form}
    return render(request, "reviews/makeselect.html", context)
于 2017-07-17T12:13:10.737 回答