custom error handler django when using django-hosts - django

I have a system that has deployed django-hosts, all is working fine. Until now I have been handling 404 and 500 errors for production by utilizing the neat trick of just placing files 500.html and 404.html in the root of the templates folder. This very nicely handles these errors in production (debug=False).
However, now I want to get a little more creative with my error handling messaging and feedback to the user. I have other projects where I have created a custom view for the error handling.
e.g.
def custom_error_500(request, exception=None):
print ('error 500 ') #For debugging to verify view is being processed.
return render(request, "errors/500.html", status=500)
and then set this parameter at the bottom of the urls.py (appname is 'main')
handler500 = 'main.errorviews.custom_error_500'
This all works very nicely in a project that does NOT use django-hosts.
The advantage of creating the custom view is that the context is past to the RequestContext to the template, whereas by default not the case (see reference).
Now, I know with django-hosts here is magic going on in the way urls.py are processed for each host. Could this be the reason why?. I tried placing the hander500 setting in all the possible urls.py that I have in project, but I get the same result, which is the system just looks for the 500.html in the root and if it does not find it displays the standard built in Server Error 500 message.
Has anyone else had the same problem? I can not believe I am the only one trying to display a customer error message using django hosts :-).
Thanks in advance for any assistance!

Related

404 when GETing from STATIC_URL does not call GET on my fallback View

In my settings.py, I have STATIC_URL='/static/'
I have a view which I use as a fallback for the static url
class MyView(View):
def get(request):
return XXX
which I add it to my urls like so
urlpatterns += [url(r'^/static/', MyView.as_view())]
Next, I want to make sure that the fallback URL is working. When I go to a bad link like localhost/static/garbage it shows me the Django 404 error page but it claims that it was raised by MyView.
What's extremely frustrating is I have two apps with the same static files handling. One of the apps trigger my view, the other does not. I cannot tell what's different that's causing the issue. Both are on whitenoise==4.1.x and django==2.3
Run under wsgi instead of runserver.
For some reason when using runserver, Django has a different static assets routing logic where MyView is bypassed and I get a different 404 page. When I switch to gunicorn everything works fine.

Django Custom Error Handlers in Apache and mod_wsgi

I have custom 404 and 500 error handlers setup in django and they work in development, but with Apache they just show the default apache Internal Server Error page, even for 404 errors.
Here is my urls.py:
handler400 = 'views.error400'
handler403 = 'views.error403'
handler404 = 'views.error404'
handler500 = 'views.error500'
I've read of many ways to set up custom error pages in apache, but all of the approaches I tried with django did not work. What is the correct way to set this up for Apache/mod_wsgi and Django?
Do I remove those lines from my urls.py and add some lines to my apache.conf?
What lines should be added to apache.conf as I'm not sure how to access views from the apache configuration file and the normal urls.py routing for Django is not working for the custom error pages since as I suspect Apache is intercepting the requests and providing it's own pages.
I just want to use my templates for my custom error pages (which include inheriting from a base template).
How can I achieve this, I can't find a decent answer anywhere?
Thanks
EDIT:
I tried editting the Apache config to add ErrorDocument 500 /templates/500.html and such but it did not work.
I currently have the error page in my templates directory, they each inherit from a base template. Also, they each have their own view to handle the responses.
But no matter what I do, removing those lines from urls.py, adding stuff to apache config, etc. I can't get anything but the typical Internal Server Error apache page to display on any error, even one's that aren't 500 errors.
What can I do to get this working? Worked fine on the django development server, but as soon as apache was thrown into the mix I can't get it to work using either apache or django, I must be missing something but what?
You can remove those lines from urls.py. Django will look up to your templates to get those.
Just put 404.html and 500.html files into your_app/templates/ directory.

Django Error Reporting Simple Syntax Errors

I'm brand new to Django and am working through the tutorial. I fat-fingered a bit of code which would normally raise a syntax error or name error if I were running the file like a standard script. However, when I try to browse to the view in my web-browser using manage.py runserver I just get a blank page with no relevant error/traceback. The same is true of the console from which I ran manage.py runserver -- it just shows the GET request. Also, when starting the server, the console displayed "0 errors found" which was clearly false.
My question is how does Django report errors and tracebacks? Do I need to enable anything? (I have DEBUG = True in my settings.py file) It's kind of un-nerving to me that I could make a little typo and all of a sudden the entire website stops working and I'm not given a report of where the problem is.
Regarding running the development server, it'll say that there are 0 errors found in getting the server started. This typically refers to configuration and syntax in your settings.py file and models. It will only report errors that come up through the startup code path, which typically it doesn't go through your view handlers.
As you modify files, the development server is smart enough to reload itself. Syntax errors will crash the development server.
If you are seeing a blank page and the GET request returning successfully, then your code is working fine from a Django perspective. It's handling the request and returning a response, though you know the response is incorrect. Typically, syntax errors here will cause the view to return a 500, where you'll see debug information returned in the view (if DEBUG = True) and you'll see it in the console as well. It would seem that your typo was valid python as it went through your view handler successfully to return a blank page. There really isn't anything you can do here other than unit tests as to Django, a blank page could be a valid response.
Now as you move from development to production, you'll likely want to know when a page runs into an error. Django builds off Python's logging framework to handle error and other messages. The defaults in your settings.py file, set up a mail_admins handler that handlers error on django.request. If you set up ADMINS and EMAIL_BACKEND in your settings file, you'll get e-mailed the stack trace for any 500 error that happens on your server. As you get more sophistication, you can create your own logging by sending messages to Python's logging framework and custom handlers.
import logging
logger = logging.GetLogger(__name__) #using the module name so in your settings.py you can configure different settings per module
logger.info('msg')
logger.error('msg')
I'd recommend looking into Sentry as a handler for your error messages, that does hit counting and stores your error logs.

is it possible to show the debug error page for the admin site only?

sooo with DEBUG = False in your settings.py, it'll show templates/500.html if there's an error etc.
with DEBUG = True, django's development error page thing will show and give you (a developer) I useful error message and debugging info
Q. In a production environment where I have DEBUG = False, is there a way to show the "development error page" for error's which occur in the Django /admin site only?
e.g. it's not neccessary to show a nice looking error page to an admin user, and I could more quickly fix a problem since an admin could just copy and paste and email the error to me, instead of me having to SSH into multiple application server things and inspect the log
Use sentry (which is also available as an open source project that you can host yourself). It will collect all the errors (no matter where they occur), give you a detailed traceback, and notify and track the errors for you.
All that with DEBUG = False.
Django's DEBUG setting does other things (like log every SQL query) which will quickly consume your server memory, but sure why not handle exceptions however you like?
Django's pretty-exception has a lot of code which sanitizes and introspects in django.views.debug but it should be straight forward to spit out a simple exception.
Just create a middleware that uses the process_exception hook.
https://docs.djangoproject.com/en/dev/topics/http/middleware/?from=olddocs#process_exception
class MyExceptionHandler(object):
def process_exception(self, request, exception):
if request.path.startswith('/admin/'):
return http.HttpResponse(
"We've encountered an exception in the /admin/ pages!")
You're free to return as much debug information as you'd like.

django on nginx & apache : where to handle 404 & 500 error?

I know there is 404 error handling in django.
But is it better to just put that config in nginx ?
This ST thread has the solution for putting it. -
http://stackoverflow.com/questions/1024199/nginx-customizing-404-page
Is that how everyone handles it when using nginx ?
I have created my own 404.html & 500.html in the sites theme, want to display them.
I didn't know how to configure 404 & 500 errors in django.
Thanks to "namnatulco" who helped me.
Here are the steps:
Create 2 pages 404.html & 500.html
Place them in your modules template folder
In your modules urls.conf, enter these two lines:
handler404 = "myproject.mymodule.views.redirect_page_not_found"
handler500 = "myproject.mymodule.views.redirect_500_error"
In your view, define the functions
def redirect_page_not_found(request):
return render_to_response('logreg/404.html', {}, context_instance=RequestContext(request));
def redirect_500_error(request):
return render_to_response('logreg/500.html', {}, context_instance=RequestContext(request));
Test it by giving some incorrect URL e.g. - www.mydomain.com/aaaaaaaaaaaaaaaa
To test 500 error, inside your view, in your render_to_response, give an incorrect URL.
That's it. You should be set.
You haven't mentioned any reasons why you would want to put these pages in the Nginx server. I would recommend keeping it with the rest of your site, that is, on the Django server. Moving part of your site to the Nginx server is a good idea to solve scalability problem, but complicates your deploy. I certainly hope you aren't seeing a significant fraction of your site's traffic going to your error pages!
I recommend using an in-Django 404/500 handler. You can deliver meaningful alternate nav suggestions in a page style that is consistent with the rest of your site.
Make sure you do not return a page talking about the error but sporting a 200 return status -- human will understand it's an error, but programmatic access will not. I'm avoiding saying "search engines" here, but the truth is that they will probably represent 98%+ of your non-human visitors. See HttpResponse subclasses for details.