Custom HTTP error pages in Django not working as intended - django

I want to make custom error pages for 404, 403, etc, but when I do anything mentioned in the documentation or any other forums/stackoverflow posts, it ignores the custom functions.
I tried this already:
How do I redirect errors like 404 or 500 or 403 to a custom error page in apache httpd?
and many others.
Am I doing something wrong?
engine(custom app) \ views.py
def permission_denied(request, exception):
context = {'e':exception}
return render(request, '403.html', context, status=403)
core (main project) \ urls.py
handler403 = 'engine.views.permission_denied'
urlpatterns = [
path('admin/', admin.site.urls),
[...]
...and it just shows the built-in error pages. Changing debug mode on or off doesn't change it.
P.E.: when I pasted the views.py function, it threw an error saying it takes 2 arguments, one for request and one for the exception, so it knows that the function is there, but when I added it to the arguments, it still got ignored.
Any advice appreciated!

Related

using Handler404 in django url dispatcher cause server error

I followed this https://stackoverflow.com/a/31381075/10087274 because I want when url does not exist a json shows error but the problem is here that I get server error 500 when I add handler404 in my url dispatcher
here is my project url :
from django.urls import path, include
from django.conf.urls import handler404
from api.exception import custom404
handler404 = custom404
urlpatterns = [
path('api/v1/', include('acl.urls')),
]
and I have exception.py inside my project folder (near settings.py) contains this:
from django.http import JsonResponse
def custom404(request):
return JsonResponse({
'status_code': 404,
'error': 'The resource was not found'
})
I dont know how can I solve my problem
Unfortunately, you haven't provided much information regarding the error traceback. Anyway, The very first thing I noticed in your code, you've missed one optional parameter to the custom404 function. That function should take two parameters, request and exception
def custom404(request, exception=None):
response = {
'status_code': 404,
'error': 'The resource was not found'
}
return JsonResponse(response, status=404)
Reference
1. Custom Error Views
Well django rest framework is open source, so if you want to replicate certain behaviour you can read the code and pick and chose what you like. For instance, you can see that the Generic Error view (custom server and bad request error views) provided in drf docs are located inside exceptions.py inside rest_framework you can look it up here and see how it can be done.
Create a custom 404 view, like this:
def not_found(request, exception, *args, **kwargs):
""" Generic 404 error handler """
data = {
'error': 'Not Found (404)'
}
return JsonResponse(data, status=status.HTTP_404_NOT_FOUND)

Custom Error Pages for django-cms

Supposedly a trivial task to server 403/404/500 error pages when using django-cms. Followed instructions on an old forum post to create this:
from cms.views import details
def custom_404(request):
response = details(request, 'page-not-found')
response.status_code = 404
return response
...
Urls.py has some lines like this:
handler404 = 'error_pages.views.custom_404'
...
From traceback django cms can't locate 404 page:
File "/home/username/.virtualenvs/venv/lib/python2.7/site-packages/cms/views.py", line 22, in _handle_no_page
raise Http404('CMS: Page not found for "%s"' % slug)
Http404: CMS: Page not found for "page-not-found"
Obviously added the required custom pages in django-cms with the slug: 'page-not-found'. Am I missing something obvious? Running on production server with debug=False. Running django-cms 2.4.2 (edit)
Perhaps it is better to just serve plain ol' error messages with hardcoded stylesheets?
After walking into countless walls over-thinking the issues, I just went with using the basic 403/404/500 handlers:
from django.utils.functional import curry
from django.views.defaults import *
handler500 = curry(server_error, template_name='500.html')
handler404 = curry(page_not_found, template_name='404.html')
handler403 = curry(permission_denied, template_name='403.html')
Created the templates for each error and put in absolute URLs for the stylesheets.
Problem solved. Wasted a bunch of time on something this trivial.
Here is a working (with DEBUG at True or False) 404 handler:
def handler404(request):
if hasattr(request, '_current_page_cache'):
delattr(request, '_current_page_cache')
response = details(request, '404')
response.status_code = 404
return response
EDIT / Easy solution
After more searching and thinking, an easier solution would be to create the default/standard 404.html, and therein use django-cms static placeholders...as easy as it gets!
Original (still working) Answer
After struggling updating my handler404 from an old cms project, and not finding any infos on this topic, and the accepted answer not being a real solution to the problem, I investigated and found a version that works in django-cms 3.4.
Worth noting
delete the _current_page_cache on the request
set request.current_page, or cms_tags will not use your 404 page and render empty
call the main cms details view for rendering the page
finally, call response.render() (as mentioned in comments)
The view
def handler404(request):
if hasattr(request, '_current_page_cache'): # we'll hit the cache otherwise
delattr(request, '_current_page_cache')
page = get_page_from_request(request, '404')
request.current_page = page # templatags seem to use this.
response = details(request, '404') # the main cms view
if hasattr(response, 'render'): # 301/302 dont have it!
response.render() # didnt know about this, but it's needed
response.status_code = 404 # the obvious
return response

Dajaxice network error 404: method not found

I'm trying to create a basic submit form (like the dajaxice's example) but i keep receiving a 404 error from firebug console:
404 NOT FOUND 386ms
"NetworkError: 404 NOT FOUND - http://<my_website>/dajaxice/maynard.maynard_core.subscribe/"
My project folder structure is
/maynard/maynard_core/
This folder contains the main files of the project (views.py, ajax.py etc etc... main django project folder)
Inside the ajax.py file, there's the subscribe method:
from dajax.core import Dajax
from dajaxice.core import dajaxice_functions
from dajaxice.decorators import dajaxice_register
from views import subscribe_search
from forms import SubscriptionForm, SendMailForm
from django.core.mail import send_mail
def subscribe(request, form):
if request.POST:
dajax = Dajax()
form = SubscriptionForm(form)
try:
if form.is_valid():
url = form.cleaned_data['url_sub']
what = form.cleaned_data['what_sub']
where = form.cleaned_data['where_sub']
mail = form.cleaned_data['email']
subscribe_search(url,what,where,mail)
dajax.assign('#sub_mess_top','innerHTML','Thank you for subscribing to the search')
else:
dajax.add_css_class('#sub_mess_top','text error-message')
dajax.assign('#sub_mess_top','innerHTML','Couldn\'t complete the request, try again!')
return dajax.json()
except:
dajax.add_css_class('#sub_mess_top','text warning-message')
dajax.assign('#sub_mess_top','innerHTML','You already saved this search')
return dajax.json()
dajaxice_functions.register(subscribe)
Which is then called via this js method
function send_form_top(){
data = $('#subscribe').serializeObject(true);
Dajaxice.maynard.maynard_core.subscribe(Dajax.process,{'form':data});
}
The form is a basic form with action "#" and onclick="send_form_top();"
I followed the installation and configuration guide (settings configured, urls configured etc etc etc), and it's a very 101 implementation.
in urls.py
from dajaxice.core import dajaxice_autodiscover
dajaxice_autodiscover()
...
django.conf.urls.defaults.url(r'^%s/' % settings.DAJAXICE_MEDIA_PREFIX, django.conf.urls.defaults.include('dajaxice.urls')),
I added 'dajaxice' to my installed apps in settings.py, and DAJAXICE_MEDIA_PREFIX is 'dajaxice' (as in the docs).
Templates are fine too (since i have the dajaxice dynamically compiled js included)
But still i can't seem to be able to make it work. I checked throu the response headers, and this is what i get for the dajax.js file:
maynard_core: {
subscribe: function(callback_function, argv, custom_settings){
Dajaxice.call('maynard.maynard_core.subscribe', callback_function, argv, custom_settings);
},
...
This tells me that the submit method, which is in the ajax.py file inside maynard/maynard_core/ is actually included and the callback is correct too. I really don't know how to debug this any more, django logs shows nothing about it. Thanks all in advance, i'm really loosing my hair on this.
If you got a 404 error, definitely the problem is in your urls.py configuration.
There is any wildcard url above the dajaxice one? Try to put the dajaxice url conf on the beginning and see what happens.
Anyway... are your views.py, ajax.py, etc... inside any app? or all of them are in the root project folder. That could be the problem too.

Custom Django 404 page and Django debug page

I am deploying a Django webpage and I love the Django Debug 404 page and and the Django page when there is a python error. However these aren't appropriate for a webpage that is going online. So I have made a custom 404 page. However, for me, and my IP address, I want to still have the Django Debug pages come up. Is there anyway to do this if I set Debug to false?
You can define your own handler-view for 404s, by setting handler404 in your urlconf. The default handler404 is django.views.defaults.page_not_found, which basically just renders the 404.html template.
If you put this in your urlconf, it will show the "technical" 404 response (the nice yellow page) for a certain IP, and use Django's default 404-production view for other IPs:
import sys
from django.views.debug import technical_404_response
from django.views.defaults import page_not_found
def handler404(request):
if request.META['REMOTE_ADDR'] == 'YOUR_IP_ADDRESS':
exc_type, exc_value, tb = sys.exc_info()
return technical_404_response(request, exc_value)
else:
return page_not_found(request)
I would advise you to set up proper logging for you 404 errors. Django can e-mail or log 404s and exceptions for you that happens in your production environment for rules that you can specify.
See the documentation on error reporting and logging (The logging framework was added in 1.3)

Django flatpages raising 404 when DEBUG is False (404 and 500 templates exist)

I'm using Django 1.1.1 stable. When DEBUG is set to True Django flatpages works correctly; when DEBUG is False every flatpage I try to access raises a custom 404 error (my error template is obviously working correctly).
Searching around on the internet suggests creating 404 and 500 templates which I have done.
I've added to FlatpageFallBackMiddleware to middleware_classes and flatpages is added to installed applications. Any ideas how I can make flatpages work?
The same happened to me until I found that the 404 view was sending a 200 status response. So all you have to do is add this in the view that handles your 404 response:
def 404_handler(request): ...
response = render_to_response('404.html', locals(), context_instance=RequestContext(request))
response.status_code = 404
return response
try to add FlatpageFallBackMiddleware before django.middleware.common.CommonMiddleware
and be sure, that your 404.html and 500.html are stored in the root of your templates dir (eg: templates/404.html)
The key is checking the order of your middleware. Middleware is executed in top-down order on the way in (request and view) and in bottom-out order on the way out (response and exception). So if you are getting to your 404 handler on what should be a perfectly reasonable flatpage URL then something is catching the 404 before the flatpages middleware is getting called.
Had the same error in a different context. The problem was caused by me changing file urls.py from
from django.conf.urls.defaults import *
to
from django.conf.urls.defaults import include, patterns
as suggested by pylint, but this omits handler404 and handler500 which are expected to be imported implicitly by import *.
so either adding those to import or just importing * as django documents suggest solved the issue.
Make an error handling view that prints a stacktrace import traceback;traceback.print_exc() instead of ignoring the error silently.