UPDATE: Added the code I was accessing that threw the error
For a CS50 project I'm working on with a wiki page, I'm trying to send the right custom 404 error when a user types a page that doesn't exist in wiki/TITLE however when I type a missing page, Django throws a 500 instead of a 404. Is this a common error or did I make my error message wrong? Debug is set to False and Allowed Hosts is configured to ['*'] in settings:
Here's my custom error handlers in views.py:
def error_404(request, exception):
context = {}
response = render(request, 'encyclopedia/error_404.html', context=context)
response.status_code = 404
return response
def error_500(request):
context = {}
response = render(request, 'encyclopedia/error_500.html', context=context)
response.status_code = 500
return response
Here's how they are in wiki/urls.py:
from django.contrib import admin
from django.urls import include, path
from django.conf.urls import handler404, handler500
urlpatterns = [
path('admin/', admin.site.urls),
path('', include("encyclopedia.urls")),
]
handler404 = "encyclopedia.views.error_404"
handler500 = "encyclopedia.views.error_500"
here's the function in views.py that I'm accessing but going to wiki/C:
#function gets entry from index.html's <li>
def entry_page(request, entry):
name = entry # Places the title
print(f"checking the title: {entry}")
text = util.get_entry(entry) # Grabs the entry using the util function
html = md_converter(text)
if text is not None:
return render(request, "encyclopedia/entry.html", {
"title": name,
"entry": html
})
And here's my urls.py for good measure:
from django.urls import path
from . import views
app_name = "encyclopedia"
urlpatterns = [
path("", views.index, name="index"),
path("wiki/<str:entry>", views.entry_page, name="entry"),
path("wiki/edit/<str:title>", views.edit, name="edit"),
path("search", views.search, name="search"),
path("random", views.random_page, name="random"),
path("create_entry",views.create_entry, name="create_entry")
]
Here's what the terminal shows (my styles.css is throwing a 404 for some reason but I haven't changed anything there...that's a separate issue):
There could be something wrong with your code. Django doc clearly says
The 404 view is also called if Django doesn’t find a match after checking every regular expression in the URLconf.
https://docs.djangoproject.com/en/3.2/ref/views/#error-views
Figured it out. Thanks ya'll.
There was an error in the function I was using to grab the page. I wasn't checking to see if the URL was valid when looking up a particular wiki entry.
Changing entry_page in views.py to this made it work!:
def entry_page(request, entry):
if entry in util.list_entries():
name = entry # Places the title
text = util.get_entry(entry) # Grabs the entry using the util function
html = md_converter(text)
return render(request, "encyclopedia/entry.html", {
"title": name,
"entry": html
})
else:
return render(request, "encyclopedia/error_404.html" )
Glad it wasn't Django messing up, just me lol
I am using django 1.10, I have following html pages register.html, login.html, home.html
Html pages are deployed on different application server. I am using Custom user model,
I can able to register and store details into database. Also able to authenticate and login into app and get redirected to home page.
Problem :
I have sample view named as, test
#viwes.py
#login_required
def test(request):
l=[]
l.append('x')
l.append('y')
return JsonResponse({"records": l})
so after login, when I directly access url as,
localhost:8000/app/test
then I am able to get data in browser.
But after login, within same session, when I am calling same url from home.html, I am not able to authenticate and receive data.
In browser console it will become as,
http://127.0.0.1:8000/accounts/login/?next=/app/test/
There were some posts which refers solution as #ajax_required, as I am new to django, I didn't find any post in detail. Can anyone please explain or suggest solution with sample example. Thanks in advance.
I have tried with below code and working file
views.py
from django.contrib.auth.decorators import login_required
from django.http.response import JsonResponse
from django.views.generic.base import View
class LoginRequiredMixin(object):
#classmethod
def as_view(cls, **initkwargs):
view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
return login_required(view)
class TestLogin(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
l = []
l.append('x')
l.append('y')
return JsonResponse({"records": l})
urls.py
from django.conf.urls import url
from django.contrib import admin
from myapp.views import TestLogin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test/$', TestLogin.as_view(), name='testview'),
]
Curl
curl -X GET -H "Cookie: csrftoken=t1l5CpH7kL5J48yf0c4C0z9kli3UfI3enCEdT4lH8RGQip1y8f8t1l3ucDWWzRGX,sessionid=99oqphuhy1udboq4pv2icgj408b1lpxi" "http://localhost:8000/test/"
So I am getting this error in django
Exception Value: Could not import reviews.views.get_user_review. View does not exist in module reviews.views.
Exception Location: /usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py in get_callable, line 118
This is my urls.py
from django.conf.urls import patterns, include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns = patterns('',
# Examples:
url(r'^$', 'feed.views.home'),
url(r'', include('social_auth.urls')),
url(r'^logged-in/$', 'custom_user.views.fb_loggedin'),
#url(r'^review/get/(?P<userid>.+?)/$', 'reviews.views.get_user_reviews_json'),
url(r'^rating/add/(?P<actor>.+?)/(?P<target>.+?)/(?P<category>.+?)/(?P<rating>.+?)/$', 'rating.views.add_rating'),
url(r'^rating/get/(?P<userid>.+?)/$', 'rating.views.get_user_ratings'),
)
urlpatterns += staticfiles_urlpatterns()
To remove the error, I've commented everything related to reviews app. But the error still exists. Here's the reviews.views
'''
from django.shortcuts import render
from models import Reviews
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.utils import simplejson
from django.core import serializers
def user_review(userid):
user = User.objects.get(id = userid)
reviews = Reviews.objects.filter(subject_user=user).select_related('user')
return reviews
#HttpResponse(data, mimetype='application/javascript')
def get_user_reviews_json(userid):
reviews = user_review(userid)
data = serializers.serialize("json", reviews)
return data
'''
EDIT:
The function get_user_reviews_json was earlier defined as get_user_review and i forgot to update the urls.py from get_user_review to get_user_reviews_json and thus got the error. but then i updated it and still the error prevails. i then commented out everything as you can see, but still the same error.
Your view should take a request object to respond to web requests. So your function should look something like below:
def get_user_reviews_json(request, userid):
reviews = user_review(userid)
data = serializers.serialize("json", reviews)
return Response(data) #from rest_framework.response import Response
Again, each view function takes an HttpRequest object as its first parameter, which is typically named request.I hope it helps.
Following the tutorial found here exactly, I cannot create a custom 500 or 404 error page. If I do type in a bad url, the page gives me the default error page. Is there anything I should be checking for that would prevent a custom page from showing up?
File directories:
mysite/
mysite/
__init__.py
__init__.pyc
settings.py
settings.pyc
urls.py
urls.pyc
wsgi.py
wsgi.pyc
polls/
templates/
admin/
base_site.html
404.html
500.html
polls/
detail.html
index.html
__init__.py
__init__.pyc
admin.py
admin.pyc
models.py
models.pyc
tests.py
urls.py
urls.pyc
view.py
views.pyc
templates/
manage.py
within mysite/settings.py I have these enabled:
DEBUG = False
TEMPLATE_DEBUG = DEBUG
#....
TEMPLATE_DIRS = (
'C:/Users/Me/Django/mysite/templates',
)
within mysite/polls/urls.py:
from django.conf.urls import patterns, url
from polls import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^(?P<poll_id>\d+)/$', views.detail, name='detail'),
url(r'^(?P<poll_id>\d+)/results/$', views.results, name='results'),
url(r'^(?P<poll_id>\d+)/vote/$', views.vote, name='vote'),
)
I can post any other code necessary, but what should I be changing to get a custom 500 error page if I use a bad url?
Under your main views.py add your own custom implementation of the following two views, and just set up the templates 404.html and 500.html with what you want to display.
With this solution, no custom code needs to be added to urls.py
Here's the code:
from django.shortcuts import render_to_response
from django.template import RequestContext
def handler404(request, *args, **argv):
response = render_to_response('404.html', {},
context_instance=RequestContext(request))
response.status_code = 404
return response
def handler500(request, *args, **argv):
response = render_to_response('500.html', {},
context_instance=RequestContext(request))
response.status_code = 500
return response
Update
handler404 and handler500 are exported Django string configuration variables found in django/conf/urls/__init__.py. That is why the above config works.
To get the above config to work, you should define the following variables in your urls.py file and point the exported Django variables to the string Python path of where these Django functional views are defined, like so:
# project/urls.py
handler404 = 'my_app.views.handler404'
handler500 = 'my_app.views.handler500'
Update for Django 2.0
Signatures for handler views were changed in Django 2.0:
https://docs.djangoproject.com/en/2.0/ref/views/#error-views
If you use views as above, handler404 will fail with message:
"handler404() got an unexpected keyword argument 'exception'"
In such case modify your views like this:
def handler404(request, exception, template_name="404.html"):
response = render_to_response(template_name)
response.status_code = 404
return response
Official answer:
Here is the link to the official documentation on how to set up custom error views:
https://docs.djangoproject.com/en/stable/topics/http/views/#customizing-error-views
It says to add lines like these in your URLconf (setting them anywhere else will have no effect):
handler404 = 'mysite.views.my_custom_page_not_found_view'
handler500 = 'mysite.views.my_custom_error_view'
handler403 = 'mysite.views.my_custom_permission_denied_view'
handler400 = 'mysite.views.my_custom_bad_request_view'
You can also customise the CSRF error view by modifying the setting CSRF_FAILURE_VIEW.
Default error handlers:
It's worth reading the documentation of the default error handlers, page_not_found, server_error, permission_denied and bad_request. By default, they use these templates if they can find them, respectively: 404.html, 500.html, 403.html, and 400.html.
So if all you want to do is make pretty error pages, just create those files in a TEMPLATE_DIRS directory, you don't need to edit URLConf at all. Read the documentation to see which context variables are available.
In Django 1.10 and later, the default CSRF error view uses the template 403_csrf.html.
Gotcha:
Don't forget that DEBUG must be set to False for these to work, otherwise, the normal debug handlers will be used.
Add these lines in urls.py
urls.py
from django.conf.urls import (
handler400, handler403, handler404, handler500
)
handler400 = 'my_app.views.bad_request'
handler403 = 'my_app.views.permission_denied'
handler404 = 'my_app.views.page_not_found'
handler500 = 'my_app.views.server_error'
# ...
and implement our custom views in views.py.
views.py
from django.shortcuts import (
render_to_response
)
from django.template import RequestContext
# HTTP Error 400
def bad_request(request):
response = render_to_response(
'400.html',
context_instance=RequestContext(request)
)
response.status_code = 400
return response
# ...
Django 3.0+ 4.0+
here is link how to customize error views
here is link how to render a view
in the urls.py (the main one, in project folder), put:
handler404 = 'my_app_name.views.custom_page_not_found_view'
handler500 = 'my_app_name.views.custom_error_view'
handler403 = 'my_app_name.views.custom_permission_denied_view'
handler400 = 'my_app_name.views.custom_bad_request_view'
and in the mentioned app (my_app_name) put in the views.py:
def custom_page_not_found_view(request, exception):
return render(request, "errors/404.html", {})
def custom_error_view(request, exception=None):
return render(request, "errors/500.html", {})
def custom_permission_denied_view(request, exception=None):
return render(request, "errors/403.html", {})
def custom_bad_request_view(request, exception=None):
return render(request, "errors/400.html", {})
NOTE: errors/404.html is the path if you place your files into the projects (not the apps) template foldertemplates/errors/404.html so please place the files where you want and write the right path.
NOTE 2: After page reload, if you still see the old template, change in settings.py DEBUG=True, save it, and then again to False and save again (that will restart the server and collect the new files).
From the page you referenced:
When you raise Http404 from within a view, Django will load a special view devoted to handling 404 errors. It finds it by looking for the variable handler404 in your root URLconf (and only in your root URLconf; setting handler404 anywhere else will have no effect), which is a string in Python dotted syntax – the same format the normal URLconf callbacks use. A 404 view itself has nothing special: It’s just a normal view.
So I believe you need to add something like this to your urls.py:
handler404 = 'views.my_404_view'
and similar for handler500.
If all you need is to show custom pages which have some fancy error messages for your site when DEBUG = False, then add two templates named 404.html and 500.html in your templates directory and it will automatically pick up this custom pages when a 404 or 500 is raised.
In Django 3.x, the accepted answer won't work because render_to_response has been removed completely as well as some more changes have been made since the version the accepted answer worked for.
Some other answers are also there but I'm presenting a little cleaner answer:
In your main urls.py file:
handler404 = 'yourapp.views.handler404'
handler500 = 'yourapp.views.handler500'
In yourapp/views.py file:
def handler404(request, exception):
context = {}
response = render(request, "pages/errors/404.html", context=context)
response.status_code = 404
return response
def handler500(request):
context = {}
response = render(request, "pages/errors/500.html", context=context)
response.status_code = 500
return response
Ensure that you have imported render() in yourapp/views.py file:
from django.shortcuts import render
Side note: render_to_response() was deprecated in Django 2.x and it has been completely removed in verision 3.x.
No additional view is required. https://docs.djangoproject.com/en/3.0/ref/views/
Just put the error files in the root of templates directory
404.html
400.html
403.html
500.html
And it should use your error page when debug is False
settings.py:
DEBUG = False
TEMPLATE_DEBUG = DEBUG
ALLOWED_HOSTS = ['localhost'] #provide your host name
and just add your 404.html and 500.html pages in templates folder.
remove 404.html and 500.html from templates in polls app.
In Django 2.* you can use this construction in views.py
def handler404(request, exception):
return render(request, 'errors/404.html', locals())
In settings.py
DEBUG = False
if DEBUG is False:
ALLOWED_HOSTS = [
'127.0.0.1:8000',
'*',
]
if DEBUG is True:
ALLOWED_HOSTS = []
In urls.py
# https://docs.djangoproject.com/en/2.0/topics/http/views/#customizing-error-views
handler404 = 'YOUR_APP_NAME.views.handler404'
Usually i creating default_app and handle site-wide errors, context processors in it.
Make an error, on the error page find out from where django is loading templates. I mean the path stack. In base template_dir add these html pages 500.html , 404.html. When these errors occur the respective template files will be automatically loaded.
You can add pages for other error codes too, like 400 and 403.
As one single line (for 404 generic page):
from django.shortcuts import render_to_response
from django.template import RequestContext
return render_to_response('error/404.html', {'exception': ex},
context_instance=RequestContext(request), status=404)
# views.py
def handler404(request, exception):
context = RequestContext(request)
err_code = 404
response = render_to_response('404.html', {"code":err_code}, context)
response.status_code = 404
return response
# <project_folder>.urls.py
handler404 = 'todo.views.handler404'
This works on django 2.0
Be sure to include your custom 404.html inside the app templates folder.
Try moving your error templates to .../Django/mysite/templates/.
I am note sure about this one, but I think these need to be "global" to the website.
In Django root urls.py file, add the below lines
from django.conf.urls import (handler400, handler403, handler404, handler500)
handler400 = 'app.views.bad_request'
handler403 = 'app.views.permission_denied'
handler404 = 'app.views.page_not_found'
handler500 = 'app.views.server_error'
In your app's views.py file, create the respective functions.
def server_error(request, exception=None):
# return render(request, '500.html')
return redirect('/')
Finally, in your settings.py file, set DEBUG = False
I had an additional
TEMPLATE_DIRS
within my settings.py and that was causing the problem.
This answer was posted as an edit to the question Django, creating a custom 500/404 error page by the OP reZach under CC BY-SA 3.0.
In urls.py, enter this code:
from django.conf.urls import (handler400, handler403, handler404, handler500)
handler404 = 'my_app.views.page_not_found_view'
then add this code in your views.py
from django.shortcuts import render,get_object_or_404
def page_not_found_view(request, exception):
return render(request, '404.html', status=404)
Dont forget to set DEBUG = False and also set ALLOWED_HOSTS = [127.0.0.1] while you are testing in your laptop.
You don't need to do anything fancy, just create a 404.html file in your templates. Go to settings.py and set:
DEBUG = False
ALLOWED_HOSTS = ["*"]
It will automatically overwrite the default.
Django > 2.2
from django.shortcuts import render_to_response, render
from django.template import RequestContext
def handler500(request, *args, **argv):
context = {}
print(request.body, '==========')
response = render(request, '500.jinja', context=context)
response.status_code = 500
return response
in urls.py
handler500 = 'apps.core.views.handler500'
How I customize the error page in Django and where do I put my html for this page.
Just create a 404.html file in your project's root level templates directory.
First you need to edit the settings.py to point to a templates folder:
Django template Path
After you have your 404.htm inside the template folder, you can follow the instructions below:
It is important to inform the search engines that the current page is a 404. You do that by changing the http header. So here it is a good way to go:
Into your application's urls.py add:
# Imports
from django.conf.urls.static import static
from django.conf.urls import handler404
from django.conf.urls import patterns, include, url
from yourapplication import views
##
# Handles the URLS calls
urlpatterns = patterns('',
# url(r'^$', include('app.homepage.urls')),
)
handler404 = views.error404
Into your application's views.py add:
# Imports
from django.shortcuts import render
from django.http import HttpResponse
from django.template import Context, loader
##
# Handle 404 Errors
# #param request WSGIRequest list with all HTTP Request
def error404(request):
# 1. Load models for this view
#from idgsupply.models import My404Method
# 2. Generate Content for this view
template = loader.get_template('404.htm')
context = Context({
'message': 'All: %s' % request,
})
# 3. Return Template for this view + Data
return HttpResponse(content=template.render(context), content_type='text/html; charset=utf-8', status=404)
The secret is in the last line: status=404
Hope it helped!
I look forward to see the community inputs to this approach. =)