POST请求中的Django 404

时间:2018-05-07 23:10:56

标签: python django

我正在尝试通过POST在我的网站上发送一个表单,但是,似乎POST URL的第一部分被切断,导致它无法匹配正确的URL。

我试图在模板中发送的表单:

<form action= "{% url 'change_portrait' %}" method="post">
        {% csrf_token %}
        <h5>Edit Portrait</h5>
        <input type="hidden" name="portrait_id" value="{{image.pk}}">
        <button type="submit" name="button" class="btn btn-primary">Submit Changes</button>
</form>

正确呈现为:

<form action= "/AdminDashboard/EditPortraits/ChangePortrait/" method="post">
        <input type='hidden' name='csrfmiddlewaretoken' value='iCt1xvIc1KZXErhbcMNepk2daHXApGih' />
        <h5>Edit Portrait</h5>
        <input type="hidden" name="portrait_id" value="14">
        <button type="submit" name="button" class="btn btn-primary">Submit Changes</button>
</form>

操作网址是正确的,也是我希望将表单提交到的位置。但是,当提交表单时,我会收到一条404,其中包含以下消息:

Using the URLconf defined in ZachWebsite.urls, Django tried these URL patterns, in this order:

^admin/
^AdminDashboard/
^ ^SundayPortraits/ [name='sunday_portraits']
^ ^Contact/ [name='contact_submission']
^ ^SubmitOrder/ [name='submit_buy_order']
^ ^BuyPrint/ [name='buy_print']
^ ^$ [name='index']
^ ^Login [name='login']
^ ^Logout [name='logout']
^ ^media\/(?P<path>.*)$

The current URL, EditPortraits/ChangePortrait/, didn't match any of these.

这是我的基础urls.py

urlpatterns = [
url(r'^AdminDashboard/', include('AdminDashboard.urls')),
url(r'^', include('mainApp.urls'))
]

和AdminDashboard.urls:

urlpatterns = [
url(r'^EditPortraits/ChangePortrait/', views.change_portrait, name='change_portrait'),
url(r'^EditPortraits/', views.edit_portraits, name='edit_portraits'),
url(r'^', views.dashboard, name='dashboard'),
]

由于某些原因,我不知道提交表单会切断最初的'/ AdminDashboard /',只针对剩余的网址'EditPortraits / ChangePortrait /'进行测试。这当然会导致它跳过基本urls.py中的第一个url模式(它应该去的地方),而是匹配catch所有第二个url,然后无法匹配mainApp.urls中的所有url。我不能为我的生活弄清楚为什么提交表单会切断行动URL的第一部分。它在内置的django开发服务器上按预期工作,但在部署到生产服务器时失败。

任何帮助都将非常感激。

修改

mainApp.urls(这些是跟踪中显示的内容,但绝不应该首先尝试):

urlpatterns = [
url(r'^SundayPortraits/', views.sunday_portraits, name='sunday_portraits'),
url(r'^Contact/', views.contact, name='contact_submission'),
url(r'^SubmitOrder/', views.submit_buy_order, name='submit_buy_order'),
url(r'^BuyPrint/', views.buy_print, name='buy_print'),
url(r'^$', views.index, name='index'),
url(r'^Login', views.login, name='login'),
url(r'^Logout', views.logout, name='logout')
]

views.change_portrait:

def change_portrait(request):
    return HttpResponse('in')

这永远不会显示它永远不会进入视图。

编辑2:

还应注意,在表单提交时,浏览器中的URL是正确的:即显示“mysite.com/AdminDashboard/EditPortraits/ChangePortrait/”。 Django出于某种原因说当前的URL是'/ EditPortraits / ChangePortrait /'。如果我在浏览器中定期访问该URL('mysite.com/AdminDashboard/EditPortraits/ChangePortrait/'),它会正确加载页面。只有当我尝试POST到该页面时才会失败。

编辑3:

可以更新视图以正确接受POST变量,如下所示:

def change_portrait(request):
    portrait_id = request.POST.get('portrait_id', None)
    return HttpResponse('in')

然而,错误仍然存​​在。

编辑4:

查看呈现模板:

def edit_portraits(request):
    if not request.session.get('logged_in', None):
        return redirect('../')

    portraits = Portrait.objects.filter(isSundayPortrait=True)
    context = {'portraits': portraits,
            'SundayPortraits': True}
    return render(request, 'AdminDashboard/editportraits.html', context)

将url(r'^ EditPortraits / ChangePortrait /',views.change_portrait,name ='change_portrait')移动到mainApp.urls(尝试匹配)会导致更新的mainApp.urls:

urlpatterns = [
    url(r'^SundayPortraits/', views.sunday_portraits, name='sunday_portraits'),
    url(r'^Contact/', views.contact, name='contact_submission'),
    url(r'^SubmitOrder/', views.submit_buy_order, name='submit_buy_order'),
    url(r'^BuyPrint/', views.buy_print, name='buy_print'),
    url(r'^$', views.index, name='index'),
    url(r'^EditPortraits/ChangePortrait/$', views.change_portrait, name='change_portrait'),
    url(r'^Login', views.login, name='login'),
    url(r'^Logout', views.logout, name='logout')
]

mainApp.views.change_portrait:

def change_portrait(request):
    if request.method == 'POST':
        return HttpResponse('POST')
    else:
        return HttpResponse('GETTING')

使用与最初显示的相同的表单,执行get请求会导致HttpResponse'GETTING'按预期方式运行。将表单更改为POST请求会产生新的堆栈跟踪:

Request Method: POST
Request URL:    http://www.example.com/EditPortraits/ChangePortrait/
Raised by:  mainApp.views.change_portrait
Using the URLconf defined in ZachWebsite.urls, Django tried these URL patterns, in this order:

^admin/
^AdminDashboard/
^ ^SundayPortraits/ [name='sunday_portraits']
^ ^Contact/ [name='contact_submission']
^ ^SubmitOrder/ [name='submit_buy_order']
^ ^BuyPrint/ [name='buy_print']
^ ^$ [name='index']
^ ^EditPortraits/ChangePortrait/ [name='change_portrait']
^ ^Login [name='login']
^ ^Logout [name='logout']
^ ^media\/(?P<path>.*)$
The current URL, ChangePortrait/, didn't match any of these.

转移到mainApp.urls(它应该捕获它)现在切断该URL的第一部分'EditPortrait /',现在只测试'ChangePortrait /'

3 个答案:

答案 0 :(得分:0)

AdminDashboard.urls中: 您的所有正则表达式都错过了$

  

注意:您的基础urls.py不需要在结尾处使用$

url(r'^EditPortraits/ChangePortrait/', 
   views.change_portrait, name='change_portrait')

好的是

url(r'^EditPortraits/ChangePortrait/$',
    views.change_portrait, name='change_portrait')

答案 1 :(得分:0)

经过更多的调查和测试,我似乎已经找到了问题所在。结果是Django如何处理script_name和path_info的问题。由于表单是发布到子URL,因此URL'/ AdminDashboard /'的第一部分被截断并保存为script_name。 URL的其余部分“EditPortrait / ChangePortrait /”被保存为path_info。然后Django尝试将path_info与url匹配。显然它没有匹配任何东西,因为它缺少已保存在script_name中的url的第一部分。改变这一行:

self.path_info = path_info

在django.core.handlers.wsgi.py中:

self.path_info = script_name + path_info

修复了问题,现在正常运作。

答案 2 :(得分:0)

你说&#34;它在内置的Django开发服务器上按预期工作,但在部署到生产服务器时失败了。

对我而言,这表示在开发服务器上不存在的生产服务器上部署存在问题。例如,也许在生产服务器上,您使用的是Apache或NGINX等Web服务器,而您在开发时并未使用它。

我会检查并仔细检查任何基础设施,例如在Django之前获取请求的Web服务器,负载平衡器等,并确保它不会重写路径或以其他方式将错误的配置传递给Django。