python - 创建或编辑模型实例时出现 Django admin 404 错误
问题描述
我目前正在调试 Django 站点的一个奇怪问题,其中一个特定模型在创建新实例或在管理界面中编辑现有实例时触发 404 错误。
具体来说,提交表单时会发生错误。我可以GET
改变表格就好了。
这仅在实时站点上发生,并且仅在保存此模型时发生。所有其他模型都按预期运行,当我在本地运行它时,一切都按预期工作。当以编程方式创建时,一切都很好,无论是在现场还是在本地。
这是我的模型:
class Content(models.Model):
"""Base Content class."""
title = models.CharField(max_length=200)
body = RichTextUploadingField(max_length=30000, blank=True, null=True, config_name='admin')
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
author = models.ForeignKey(to=User, on_delete=models.CASCADE)
slug = models.SlugField(max_length=100, null=True, default=None)
class Meta:
abstract = True
class ContentPage(Content):
"""Represents a page of generic text content."""
title = models.CharField(max_length=200, unique=True)
has_url = models.BooleanField(default=False, help_text='Sets the page to accessible via a URL.')
banner = models.ImageField(upload_to='myfiles/banners/', blank=True, null=True)
def save(self, *args, **kwargs):
"""Create the slug from the title."""
self.slug = slugify(self.title[:100])
super(ContentPage, self).save(*args, **kwargs)
ContentPage
该类是在管理界面中触发问题的类。我的另一个继承自的类Content
工作正常。
我已将我的管理员设置剥离为以下内容,但它仍在发生:
class CustomAdminSite(AdminSite):
def get_urls(self):
"""Define custom admin URLs."""
urls = super(CustomAdminSite, self).get_urls()
# Append some new views here...
return urls
admin_site = CustomAdminSite()
admin_site.register(ContentPage)
这是重现问题的基本 URL 配置:
from myapp.admin import admin_site
urlpatterns = [
path('mycooladminsite/', admin_site.urls),
path('', include('myapp.urls')),
]
我检查过的其他几件事:
- 我没有干扰保存的信号。
- 我没有在模型的
save()
方法中执行任何操作。 - 我检查了
get_object_or_404()
电话,看不到任何会影响这一点的电话。
我花了几个小时来挖掘这个,我现在在一堵砖墙上。
数据库引擎是mysql.connector.django
Django 版本 2.2.11。我还不能为此站点更改引擎或将 Django 更新到 3.x。
这是我之前没有注意到的最近的一个问题。
更新:
我已将问题范围缩小到 ImageField。当我从显示的字段中删除它时,保存时不会出现问题。
我正在使用自定义管理表单,但这似乎不是问题。我试过使用默认值,它仍然会发生。我一直在寻找存储类中的异常,但没有发现任何异常。我一直把它剥离回来,错误仍然存在。
我在 Firefox 开发者工具中检查了本地 302POST
和生产 404 POST
,它们实际上是相同的,但是生产服务器是 Apache 并且x-powered-by
是 Phusion Passenger,而本地服务器是 WSGIServer/0.2 CPython/3.7.3。
我实际上已经注意到multipart/form-data
现在生产中的其他形式出现了 404,这是我以前从未遇到过的。
解决方案
我从来没有完全了解发生了什么,但我确实设计了一种解决方法,至少可以让表单正常运行,正如我在对相关问题的回答中所讨论的那样:
_get_response(self, request)
中编辑django.core.handlers.base
。更改resolver_match = resolver.resolve(request.path_info)
为resolver_match = resolver.resolve(request.path)
。添加此中间件(根据您的确切需求进行调整):
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
无论如何都不理想,但目前对我有用。
您可以在此处阅读更多详细信息: https ://medium.com/@mnydigital/how-to-resolve-django-admin-404-post-error-966ce0dcd39d
我相信这些问题至少部分是由 ModSecurity Apache 引起的。在托管服务提供商后来重新配置后,我已经解决了一些问题。
推荐阅读
- mysql - 将列名作为参数传递给 mySQL 中的存储过程
- css - 使用 d-flex 使内容居中。尝试使用 d-flex (bootstrap4) 将 div 中的内容对齐为相同
- r - 如何收集数据框以使列成为单列
- javascript - 如何使用循环在 Pug 中创建可切换的 Bootstrap?
- python - 如何在 SQLAlchemy 中连接来自不同数据库的 2 个表?
- c# - 统一弹丸产生但不加快速度?
- python-3.x - 如何用 Bokeh 回调自定义 JS 计算切线?
- jquery - jQuery 从 JSON 返回的数组中获取特定的键值
- node.js - 如何在 Node.js 中上传和显示文件?
- python - 用漂亮的汤和蟒蛇刮桌