I have a problem with the Django site deployed on Namecheap shared hosting running cPanel/Apache.
Recently a problem that started out as relatively infrequent has become a regular occurance, without any change on my side.
When submitting a POST
request in an admin form that has an ImageField, a 404 response is returned and I see the handler404
view. This does not happen locally or with my deployments on Heroku or Google Cloud Platform so I am saying it is a specific issue with this server setup. GET
requests to the same server work perfectly fine, however, as do forms without images.
Through much testing with a broken admin change view, I have located the source of the problem to the URLResolver
in django.urls.resolvers
. I’ve added a few logging calls and have noticed that a match is not being found due to differences in the URL structure:
The URLResolver
actually first matches the URL:
PATH: /myadmin/myapp/mymodel/1/change/
MATCHED PATTERN: ^/
PATH: myadmin/myapp/mymodel/1/change/
MATCHED PATTERN: myadmin/
PATH: myapp/mymodel/1/change/
MATCHED PATTERN: myapp/mymodel/
ResolverMatch(func=django.contrib.admin.options.change_view, args=(), kwargs={'object_id': '1'}, url_name=myapp_mymodel_change, app_names=[], namespaces=[], route=<path:object_id>/change/)
It then tries to process it again, this time without the myadmin/
prefix, so it obviously doesn’t match anything and nothing is updated.
PATH: /myapp/mymodel/1/change/
MATCHED PATTERN: ^/
PATH: myapp/mymodel/1/change/
FAILED PATTERN: myadmin/
...
Not Found: /myadmin/myapp/mymodel/1/change/
I don’t know why the path is handled differently this second time around (or indeed why it is handled twice). There are no path issues when I run it locally.
Putting aside the fact that this is not the best place to host a Django site (which I’m aware of and can’t really change at the moment), what might be a way of resolving this?
To experiment, I’ve tried:
- Editing
_get_response(self, request)
indjango.core.handlers.base
to doresolver.resolve(request.path)
rather thanresolver.resolve(request.path_info)
. This now allows the model to be updated, unlike before, but a 404 is still returned. - Looking to see if
httpd.conf
can be edited to set aWSGIScriptAlias
, but shared hosting doesn’t allow that.
This seems to be an issue that others are having with the same setup:
I am a new user so can’t post additional links but there is one on StackOverflow with
URL /questions/57344774/django-admin-returns-404-on-post-200-on-get
.
None of these have any solutions.
Any ideas would be appreciated. The project URLs are defined as follows:
# Import custom AdminSite that just adds a couple of views.
from myapp.admin import admin_site
urlpatterns = [
path('', include('myapp.urls')),
re_path(r'^myadmin/', admin_site.urls),
re_path(r'^ckeditor/', include('ckeditor_uploader.urls')),
re_path(r'^maintenance-mode/', include('maintenance_mode.urls')),
path('sitemap.xml', index, {'sitemaps': sitemaps}),
path('sitemap-<section>.xml', sitemap, {'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap')
]