多种形式单视图Django

时间:2013-01-25 19:21:18

标签: django parameters django-forms

这是我的场景:我在页面上有多个选择框,用户从ModelChoiceField中选择选项,并重定向到一个视图,其中选定的选项作为参数传递。类似的东西:

class BrowseForm(forms.Form):
    thing = forms.ModelChoiceField(queryset=Thing.objects.all(), empty_label=None, widget=forms.Select(attrs={'onchange': 'this.form.submit();'}))
    stuff = forms.ModelChoiceField(queryset=Stuff.objects.all(), empty_label=None, widget=forms.Select(attrs={'onchange': 'this.form.submit();'}))

视图:

def browse(request):
    thing_list = Thing.objects.all()
    if request.method == 'POST':
        form = BrowseForm(request.POST)
        if form.is_valid():
            thing = form.cleaned_data['thing']
            stuff = form.cleaned_data['stuff']
            return HttpResponseRedirect(reverse('browse_thing', kwargs={'thing':thing, 'stuff':stuff}))
    else:
        form = BrowseForm()
    return render(request, 'browse.html', {'form':form, 'thing_list':thing_list})

这要求我提交BrowseForm的两个字段,但我希望thingstuff有两个不同的网址,其中thing或{{ 1}}作为参数传递,而不是两者。类似的东西:

stuff

有没有办法用一个表单和一个视图执行此操作?或者我是否需要为url(r'^browse/things/(?P<thing>[\w-]+)/$', 'views.browse', name='browse_thing'), url(r'^browse/stuff/(?P<stuff>[\w-]+)/$', 'views.browse', name='browse_stuff'), thing编写不同的表单,然后检查在我的视图中传递哪个表单并相应地重定向到相应的URL?你会怎么做?谢谢你的想法!

2 个答案:

答案 0 :(得分:0)

您可以选择根据是否传入thingstuff来显示各种元素,因此您的视图会显示:

def browse(request, thing=None, stuff=None):
    # your code, then...
    return render(request, 'browse.html', {
        'form': form,
        'thing_list': thing_list,
        'stuff_list': stuff_list,
        'has_thing': bool(thing),
        'has_stuff': bool(stuff)
    })

然后在您的模板中,您可以执行以下操作:

{% for f in form %}
    {% if f.name == 'thing' and has_thing %}
        <!-- render it -->
    {% endif %}
    {% if f.name == 'stuff' and has_stuff %}
        <!-- render it -->
    {% endif %}
{% endfor %}

另请注意在required=False字段中设置BrowseForm,这样就不会在POST上收到验证错误,因为您只有一个或另一个。

答案 1 :(得分:0)

虽然看起来不是很干,但这就是我解决问题的方法:

forms.py:

class StuffBrowseForm(forms.Form):
    stuff = forms.ModelChoiceField(queryset=Stuff.objects.all(), widget=forms.Select(attrs={'onchange': 'this.form.submit();'}))

class ThingBrowseForm(forms.Form):
    thing = forms.ModelChoiceField(queryset=Thing.objects.all(), widget=forms.Select(attrs={'onchange': 'this.form.submit();'}))

视图:

def browse(request):
    thing_list = Thing.objects.all()
    if request.method == 'POST':
        form1 = StuffBrowseForm(request.POST)
        form2 = ThingBrowseForm(request.POST)
        if form1.is_valid():
            stuff = form1.cleaned_data['stuff']
            return HttpResponseRedirect(reverse('browse_stuffs', kwargs={'stuff':stuff}))
        elif form2.is_valid():
            thing = form2.cleaned_data['thing']
            return HttpResponseRedirect(reverse('browse_things', kwargs={'thing':thing}))
    else:
        form1 = StuffBrowseForm()
        form2 = ThingBrowseForm()
    return render(request, 'browse.html', {'form1':form1, 'form2':form2, 'thing_list':thing_list})

网址:

url(r'^browse/$', 'views.browse', name='browse'),
url(r'^browse/stuff/(?P<stuff>[\w-]+)/$', 'views.browse_stuffs', name='browse_stuffs'),
url(r'^browse/things/(?P<thing>[\w-]+)/$', 'views.browse_things', name='browse_things'),