I generally add a catch-all 404 regex to my Django websites as the last expression in my urls.py:
urlpatterns += patterns('django.views.generic.simple',
(r'^.', 'direct_to_template', {'template': 'unknown.html'}),
I'm generally happy with the performance of this. The unknown.html template extends my base template and nicely tells the viewer that their entered url doesn't exist, but the page still has all the navigation and style of my website.
However, after having to repeatedly tell people to enter a trailing slash, I feel that the APPEND_SLASH = True parameter in settings.py needs to be set.
the docs state:
If APPEND_SLASH is True and the
initial URL doesn’t end with a slash,
and it is not found in the URLconf,
then a new URL is formed by appending
a slash at the end. If this new URL is
found in the URLconf, then Django
redirects the request to this new URL.
Otherwise, the initial URL is
processed as usual.
So following this logic, foo.com/bar is successfully caught by my "404" url expression before it can be redirect to my foo.com/bar/ url expression.
*What is the best way to maintain a friendly/custom catchall 404 page while also being able to use APPEND_SLASH or something with similar functionality?*
--edit/answer--
Somehow I missed that you just need to add a template named 404.html, and also make sure DEBUG = False
Thanks DTing!
I think you can just customize your 404.html instead of using a "catchall" since you are just redirecting to a custom template. There is no reason why your custom 404.html template can't extend your site's base.html.
http://docs.djangoproject.com/en/dev/topics/http/views/#customizing-error-views
Three things to note about 404 views:
The 404 view is also called if Django doesn't find a match after
checking every regular expression in
the URLconf.
If you don't define your own 404 view -- and simply use the default,
which is recommended -- you still have
one obligation: you must create a
404.html template in the root of your template directory. The default 404
view will use that template for all
404 errors. The default 404 view will
pass one variable to the template:
request_path, which is the URL that
resulted in the 404.
The 404 view is passed a RequestContext and will have access to
variables supplied by your
TEMPLATE_CONTEXT_PROCESSORS setting
(e.g., MEDIA_URL).
If DEBUG is set to True (in your settings module), then your 404 view
will never be used, and the traceback
will be displayed instead.
if you do want to use a custom view,
This page_not_found view should
suffice for 99% of Web applications,
but if you want to override the 404
view, you can specify handler404 in
your URLconf, like so:
handler404 = 'mysite.views.my_custom_404_view'
Related
I moved a 20 year old classic asp web site to a django app recently. Google Search Console is showing 500 errors for tons of very old URLS with parameters like /somefile.asp?ID=1234&name=some-name. Most of these URLS I don't even care about - they are really old but would rather they result in 404 than 500. Some do relate to newer content and in theory I could redirect to new django pages but when I try to redirect them using the django redirect app, the site shows 500 errors - like the ? either stops the pages from ever getting to the redirect middleware or the redirect app doesn't like the "?". How can I redirect these urls so I don't get 500 errors? Is there a way in a view to say:
if the full url path is x
redirect to full url path y
I have looked all over stack overflow and elsewhere and can't find this exact problem or a way to write a view like this. I did try the solution here (exactly) because it seems closest to my issue, but it did not work for me for this exact problem: Django's redirects app doesn't work with URL parameters
An example would be /profiles/?adid=134&v=857
The error with debug true is:
DoesNotExist at /profiles/
BusinessCategory matching query does not exist....
So it is trying to match this URL:
path('<slug:slug>/', views.view_category_list, name='view_category_list'),
before it ever gets to the /?
Relevant view code:
def view_category_list(request, slug):
try:
category_detail = BusinessCategory.objects.get(slug=slug)
except BusinessCategory.DoesNotExist:
category_detail = None
if category_detail:
--code here is all working fine so removed it to get to the issue--
else:
raise Http404
I hoped raising the 404 would call up the redirect app to do its job at redirecting to a specific url but it doesn't - it just shows the custom 404 when debug is False. Anyway, the 404 is better than the 500 for SEO purposes but I still would prefer being able to actually redirect some of the URLs to relevant content.
I tried this,
url ('', views.notfound, name='notfound')
But seems it doesn't work properly, for example, I have another url pattern define,
url(r'^login/$', views.login, name='login'),
So, if I go for http://example.com/login/, this works, but if i go for http://example.com/login/?help=1, then it falls into notfound category. How can I handle that?
If you just want to create a page that is displayed when a URL is not found (i.e. a Http404 exception is thrown) you can create a template with the name 404.html, and that template will be displayed any time a URL is not found.
Or if you want to define a custom 404 handler view you can define handler404 = views.notfound in your urls.py file. Then just create your notfound view, and that view will be used whenever a 404 error is thrown (and DEBUG = False)
This is a better way to catch any urls that are not recognized and display a friendly 404 page.
You can try with regex like this:
url(r'^.*', views.notfound, name='notfound'),
Make sure put it at the end of the urls.py
I think you may need to do something when url is not found, if you just need the 404 page, then the single 404.html in your templates works. And remember ti set DEBUG = False in your settings.py to see the 404 page in development environment.
Don't know what your use case is.Both above comments were equally right enough if u want to display a custom 404 page .Had u need something else to know. Check this out->
pip install django-extensions
then read this
then use the show-urls command to enlist all possible urls.
Do some manipulation or write testcases with assert to check not found urls.
Hope this is ok for your requirements or kindly comment with your suggestions cheers :-)
I'm getting a 404 from my Django server even though it's aware of my view code. If I purposely misspelled the name of the view function, Django complains, so I know it's looking in the right place and that it is aware of this function.
My urls.py entry looks like this
url(r"^pdfgen/$", 'apps.pdfgen.views.pdfgen'),
And my view code is this
def pdfgen(request):
html = "<html><body>This is a test.</body></html>"
return HttpResponse(html)
So why is it that Django 404's when I visit localhost:xxxx/pdfgen/ ?
If I purposely misspelled the name of the view function, Django complains, so I know it's looking in the right place and that it is aware of this function.
That doesn't mean that your request is hitting the correct view - it just means that Django can't load your url conf when you include views that don't exist. To be sure that Django is running the view you think it is, you need to add some logging or print statements to the view, or raise an exception in it.
Update your question to include all your url patterns. Your request is probably matching a view further up, which is returning the 404.
I've got a prob with a link in the sidebar of my django site, in the template it's like that:
<li>Profile</li>
while in the urls.py:
url(r'^(?P<user_id>\d+)/profile/$', 'auth.views.show_profile', name='profile')
When i access it from the main page with url: e.g /1001/profile/ it loads fine but when I try to access it from another subpage with url: e.g /1001/forms/profile/ i get the error: The current URL, /1001/forms/profile/, didn't match any of these. How can i fix this?
It is because "profile" is a relative URL, and a relative URL is appended to the current URL - the resulting address is not valid across the whole site. Seems like you should use an absolute URL in your case.
At the template you can try something like:
Profile
UPDATE
To get request available in templates you have to add django.core.context_processors.request to TEMPLATE_CONTEXT_PROCESSORS. I'm not sure if it is added by default.
You must have to add your second subpage url in urls like you did for /1001/profile/
url(r'^(?P<user_id>\d+)/form/profile/$', 'auth.views.show_profile', name='profile_form')
and also correct your code as #Paulo mentioned or you can also do it through reverse url.
Profile
i am trying to define a url pattern in django urls.py like
url(r'^networking$','mysite1.networking.views.networking'),
when i am typing http://myhost.com/networking in my address bar to go to networking page
i am getting 404 error and a slash '/' automatically added to the address bar like
http://myhost.com/networking/
help me out what i am doing wrong?
You probably aren't including your urlconf correctly. The behavior you're seeing is because of APPEND_SLASH is set to True by default when Django can't resolve the url.
Either set Append_Slash to false which is true by default or use your url description like given below which redirect url with slash to desired view.
url(r'^networking/$','mysite1.networking.views.networking'),
Seems your Apache server or some Django middleware is adding trailing slashes. You can either correct that, or the better way is you can use the following url pattern:
url(r'^networking/?$','mysite1.networking.views.networking'),