Django管理员在POST上返回404,在GET上返回200

时间:2019-08-04 07:40:35

标签: python django

在生产服务器上,当我尝试编辑/创建对象时,保存失败,返回404。这仅在POST请求中发生,GET请求(加载页面)可以正常工作。 Django是通过cPanel和WSGI部署的,DEBUG为False(尽管即使将其设置为True也无法使用)

我已经将cpanel部署在Django应用中,并在virtualenv中运行。这似乎只发生在使用FileField进行文件上传的模型中,可以很好地更改/创建其他模型。

模型:

def get_image_path(instance, filename):
    name, ext = filename.split('.')
    return f'images/{instance.advert_id}/{name}.{ext}'

class AdvertImage(models.Model):
    advert = models.ForeignKey(Advert, on_delete=models.CASCADE)
    image = models.ImageField(upload_to=get_image_path)

URL conf:

urlpatterns = [
                  path('i18n/', include('django.conf.urls.i18n')),
              ] + i18n_patterns(
    path('admin/', admin_site.urls),

    # ... other views....

    prefix_default_language=False
)

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

导航到domain.com/admin/colli/advertimage/1/change/-页面正确加载。填写表格,点击保存。

应保存模型,并且不会出现404。
其他不使用FileField的模型,因为所有模型的管理员视图均正常工作

对于DEBUG = True,完整的错误消息为:

Page not found (404)
Request Method: POST
Request URL:    http://example.com/admin/colli/advertimage/1/change/
Raised by:  django.contrib.admin.options.change_view
Using the URLconf defined in Colli.urls, Django tried these URL patterns, in this order:

i18n/
admin/
[name='home']
advert/<slug:slug> [name='detail']
tagauks [name='admin_list']
tagauks/lisa [name='insert']
tagauks/muuda/<int:pk> [name='edit']
tagauks/kasutaja/<int:pk> [name='user_edit']
tagauks/save_image [name='save_image']
accounts/login/ [name='login']
accounts/logout/ [name='logout']
api/
^media/(?P<path>.*)$
The current path, colli/advertimage/1/change/, didn't match any of these.

You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.

引起这种情况的视图似乎是change_view

2 个答案:

答案 0 :(得分:1)

您是否激活了中间件(Internationalization: in URL patterns)?

# settings.py
MIDDLEWARE = [
...
'django.middleware.locale.LocaleMiddleware'
...
]

答案 1 :(得分:0)

我从来没有深入了解这个问题,但是我已经开发出一种解决方法,可以使表单起作用。

  1. _get_response(self, request)中编辑django.core.handlers.base。将resolver_match = resolver.resolve(request.path_info)更改为resolver_match = resolver.resolve(request.path)

  2. 添加此中间件(根据您的实际需求进行调整):

     class ImageField404Middleware:
         def __init__(self, get_response):
             self.get_response = get_response
    
         def __call__(self, request):
             response = self.get_response(request)
    
             if (request.method == 'POST' and request.user.is_superuser and response.status_code == 302
                     and request.get_full_path().startswith('/pathtoadmin/')):
                 post_messages = get_messages(request)
                 for message in post_messages:
                     if ('was added successfully' in message.message or 'was changed successfully' in message.message
                             and message.level == message_levels.SUCCESS):
                         messages.success(request, message.message)
                         redirect_url = request.get_full_path()
                         if '_addanother' in request.POST:
                             redirect_url = re.sub(r'[^/]*/[^/]*/$', 'add/', redirect_url)
                         elif '_save' in request.POST:
                             redirect_url = re.sub(r'[^/]*/[^/]*/(\?.*)?$', '', redirect_url) 
                             if '_changelist_filters' in request.GET:
                                 preserved_filters = parse.parse_qsl(request.GET['_changelist_filters'])
                                 redirect_url += '?' + parse.urlencode(preserved_filters)         
                         elif '_continue' in request.POST:
                             redirect_url_search = re.search(r'((?<=href=)[^>]*)', message.message)    
                             if redirect_url_search:                                                  
                                 redirect_url = redirect_url_search.group(0)                                                  
                                 redirect_url = re.sub(r'[\\"]*', '', redirect_url).replace('/pathtoadmin/pathtoadmin/', '/pathtoadmin/')
                         return HttpResponseRedirect(redirect_url)
    
             return response
    

无论如何都不理想,但目前对我有用。

我认为这些问题至少部分是由ModSecurity Apache引起的。托管服务提供商后来重新配置了此设置后,我遇到了一些问题。

您可以在此处阅读更多详细信息:https://medium.com/@mnydigital/how-to-resolve-django-admin-404-post-error-966ce0dcd39d