【问题标题】:Django HTML POST parameters causes NoReverseMatchDjango HTML POST 参数导致 NoReverseMatch
【发布时间】:2017-05-14 15:45:15
【问题描述】:

我有一个带有两个下拉列表的 HTML 帖子,我想将这些列表中选定的 Country 发送到 views.py 中的 search() 方法,然后将我发送到 results 视图。每当我添加 governmentlocation 作为 html POST 操作的参数或在搜索正则表达式中添加它们的值时,我尝试这个我从我的 index 页面得到一个 NoReverseMatch

未找到带有参数“(”,“”)和关键字参数“{}”的“搜索”。尝试了 1 种模式:['search/(?P[A-Z]{3})/(?P[A-Z]{3})/']

我不会因为我做错了什么而导致这个错误。 (见代码中的cmets)

应用名称/views.py:

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from .models import Country, Embassy
from django.template import loader
from django.urls import reverse


def index(request):
    country = Country.objects.filter()
    template = loader.get_template('appname/index.html')
    context = {'countries': country}
    return render(request, 'appname/index.html', context)

def results(request, government, location):
    return HttpResponse("Here are the Embassies sent by %s, located in %s." % (government, location))

def search(request):
    countries  = Country.objects.all()
    form = request.POST
    if request.method == 'POST':
        try:
            selected_government = get_object_or_404(pk=request.POST['government'])
        except (KeyError, Country.DoesNotExist):
            return render(request, 'appname/index.html', {
                'error_message': "You didn't select a government.",
            })
        try:
            selected_location = get_object_or_404(pk=request.POST['location'])
        except (KeyError, Country.DoesNotExist):
            return render(request, 'appname/index.html', {
                'error_message': "You didn't select a location.",
            })
        else:
            return HttpResponseRedirect(reverse('appname:results', args=(selected_government.code,selected_location.code,)))

应用名称/模板/应用名称/index.html:

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

# government and location in the form action causes a NoReverse Match
<form action="{% url 'appname:search' government location %}" method="POST"> 
    {% csrf_token %}
    <label>Find Embassies sent by</label>
    <select name="government">
        {% for entry in countries %}
            <option value="{{ entry.code }}">{{ entry.name }}</option>
        {% endfor %}
    </select>
    <label>that are located in</label>
    <select name="location">
        {% for entry in countries %}
            <option value="{{ entry.code }}">{{ entry.name }}</option>
        {% endfor %}
    </select>
    <input type="submit" value="Search" />
</form>

urls.py:

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^', include('appname.urls')),
    url(r'^appname/', include('appname.urls')),
    url(r'^admin/', admin.site.urls),
]

应用名称/urls.py:

from django.conf.urls import url

from . import views

app_name = 'appname'
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^(?P<embassy_id>[0-9]+)/$', views.embassy_info, name='embassy_info'),
    url(r'^(?P<code>[A-Z]{3})/$', views.country_info, name='country_info'),
    url(r'^find/(?P<government>[A-Z]{3})/(?P<location>[A-Z]{3})/$', views.results, name='results'),
    # the government and location values in search regex also cause a NoReverse Match   
    url(r'^search/(?P<government>[A-Z]{3})/(?P<location>[A-Z]{3})/', views.search, name='search'),
]

应用名称/models.py:

from django.db import models

class Country(models.Model):
    code = models.CharField(primary_key=True, max_length=3)
    name = models.CharField(max_length=50, db_column="Name")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'Country'
        verbose_name_plural = 'Countries'


class Embassy(models.Model):
    government = models.ForeignKey(Country, on_delete=models.CASCADE, related_name="government")
    location = models.ForeignKey(Country, on_delete=models.CASCADE, related_name="location")
    name = models.CharField(max_length=200, db_column="Name")
    street_address = models.CharField(max_length=200, db_column="Address")
    city = models.CharField(max_length=50, db_column="City")
    phone_number = models.IntegerField(default=-1, db_column="Phone Number")
    fax_number = models.IntegerField(null=True, blank=True, db_column="Fax Number")
    email_address = models.CharField(max_length=200, db_column="Email")
    website = models.CharField(max_length=200, db_column="Link")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'Embassy'
        verbose_name_plural = 'Embassies'

【问题讨论】:

    标签: python html django post


    【解决方案1】:

    它不是那样工作的。 url 标签的参数——实际上就像任何模板标签一样——必须来自渲染时传递给模板的上下文。但是您正在尝试从表单本身动态使用值。

    您应该从 URL 模式中完全删除参数。无论如何,您都没有在视图中使用它们,因为您从 request.POST 正确获取了值。

    url(r'^search/$', views.search, name='search'),
    

    ...

    <form action="{% url 'search' %}" ...
    

    【讨论】:

    • 现在我从views.py 中的selected_government = get_object_or_404(pk=request.POST['government']) 行得到get_object_or_404() missing 1 required positional argument: 'klass' 错误,但不确定它是什么意思。在我的代码中没有使用“klass”
    • 你需要告诉那个函数使用什么模型:get_object_or_404(Government, pk=request.POST['government']).
    • 我认为你的意思是Country,但你没看错。
    【解决方案2】:

    您需要使用ModelChoiceField 创建一个表单。

    forms.py

    from django import forms
    from models import Country
    
    class SearchForm(forms.Form):
        government = forms.ModelChoiceField(queryset=Country.objects.all(), to_field_name="code", label="Find Embassies sent by")
        location = forms.ModelChoiceField(queryset=Country.objects.all(), to_field_name="code", label="that are located in")
    

    views.py

    from forms import SearchForm
    
    def index(request):
        form = SearchForm()
        context = {'form': form}
        return render(request, 'appname/index.html', context)
    
    
    def search(request):
        form = SearchForm(request.POST or None)
        if request.POST and form.is_valid():
            govt = form.cleaned_data.get('government')
            loc = form.cleaned_data.get('location')
            return HttpResponseRedirect(reverse('appname:results', kwargs={"government": govt.code, "location": loc.code}))
        else:
            context = {'form': form}
            return render(request, 'appname/index.html', context)
    

    appname/urls.py 中 添加此网址

    url(r'^search/$', views.search, name='search'),
    

    index.html

    <form method="post" action={% url 'appname:search' %}>
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit" value="Search" />
    </form>
    

    【讨论】:

      【解决方案3】:

      Django URL 解析器反向将关键字参数作为参数

      reverse('search', kwargs={'government':goverment.code, 'location':location.code})
      

      希望对你有帮助

      【讨论】:

      • 谢谢,但它似乎不起作用,我仍然遇到同样的错误。
      • 您没有在基本应用程序 url 中配置命名空间。所以你不应该需要 appname 作为前缀。更新了我的答案
      • 你的意思是app_name = 'appname'
      • 没有在你的基础应用 urls.py 中包含类似 include('appname.urls'), namespace='appname')
      • 你是对的,但这似乎与我的问题无关。尤其是现在已经解决了。
      猜你喜欢
      • 1970-01-01
      • 2020-10-14
      • 2020-06-07
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多