I'm trying to customize the 404 error pages in my application. After searching many possible solutions, I created an 404.html template, added a method which should handle HTTP Error 404 and edited my urls.py.
But I guess I'm doing something really wrong. My log presents an invalid syntax error and I cannot solve it.
My views.py:
# HTTP Error 400
def page_not_found(request):
response = render_to_response('404.html',context_instance=RequestContext(request))
response.status_code = 404
return response
And the syntax error:
Traceback (most recent call last):
File "/.../myenv/lib/python3.4/site-packages/django/core/urlresolvers.py", line 393, in urlconf_module
return self._urlconf_module
AttributeError: 'RegexURLResolver' object has no attribute '_urlconf_module'
...
File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
File "/home/dcaled/work/portal-interface/portal/urls.py", line 12
handler404 = 'views.handler404'
^
SyntaxError: invalid syntax
Does anyone have an idea of what's going on?
Thanks.
UPDATE:
After #Alasdair suggestion, I made some changes and fixes. The error has stopped.
Now, my urls.py is like:
handler404 = 'views.page_not_found'
urlpatterns = [
url(r'^$', views.home),]
But I still don't get my custom 404.html when accessing a non existing page.
Instead, a default page is loaded, with this message:
"Not Found
The requested URL /url/404 not found on this server."
Also, my settings.py:
DEBUG = False
ALLOWED_HOSTS = ['*']
TEMPLATE_DIRS = (os.path.join(BASE_DIR , 'portal/templates'),)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
My project tree:
├── fb_dev
│ ├── __init__.py
│ ├── __pycache__
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
│
└── portal
├── admin.py
├── forms.py
├── json
├── migrations
├── models.py
├── static
├── templates
│ ├── 404.html
│ └── portal
│ ├── base.html
│ ├── home.html
├── templatetags
├── urls.py
└── views.py
After some months, I revisited the problem and identified a solution. Here is the answer:
a) I removed page_not_found method from the views.py. There's no need to add it. Django automatically gets and renders the 404.html template.
b) Once again, there's no need to edit urls.py. So I removed this line:
handler404 = 'views.page_not_found'
c) Also, it is necessary to edit settings.py, setting DEBUG to FALSE.
DEBUG = False
And I removed the following line:
TEMPLATE_DIRS = (os.path.join(BASE_DIR , 'portal/templates'),)
d) Finally, I created a 404.html template in my portal/templates directory. It is worth noticing that the custom template was rendered only when placed inside this directory.
After some troubles, the revy solution worked perfectly. So, just to clarify:
The Two things to do are:
Add a 404.html file in your_app/template/404.html
Set your DEBUG value to False
After that, Django will render automatically your template.
The handler404 should be outside urlpatterns. If the view is called page_not_found, then it should refer to page_not_found, not handler404.
handler404 = 'views.page_not_found'
urlpatterns = [
url(r'^$', views.home),
]
However, in your case, you do not need a custom 404 handler at all. Remove the handler404 line completely, and the default page_not_found view will render your 404.html template.
Related
Wup, I'm trying to deploy a localhost web using Django but I get the following error:
TemplateDoesNotExist at /
templates/index.html
Request Method: GET
Request URL: http://127.0.0.1:8000/
Django Version: 4.1.2
Exception Type: TemplateDoesNotExist
I was looking tutorials and docs but I didn't found the answer.
Here is my settings.py
ALLOWED_HOSTS = ['*']
DEBUG = True
ROOT_URLCONF = 'FortyTwop.urls'
SECRET_KEY = 'This is a secret key'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ["templates"],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
also urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index')
]
And views.py
from email import message
from http.client import HTTPResponse
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, 'index.html')
My path tree:
.
├── FortyTwop
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── templates
│ │ └── index.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
└── manage.py
What Im doing bad or what I didn't have in the settings?, this project is just for test.
templates/ is the base path you've configured in the settings, so you'll want
def index(request):
return render(request, 'index.html')
Furthermore, TEMPLATE_DIRS hasn't been a thing since Django 1.8 or so, and you're on Django 4.x. See these instructions.
I was just checking out django, and was trying a view to list the books by passing id as an argument to the URL books/urls.py. But getting 404 page not found error. I'm not getting whats wrong in the url when I typed this url in the browser:
http://192.168.0.106:8000/books/list/21/
bookstore/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', include("books.urls"))
]
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'books'
]
...
...
...
ROOT_URLCONF = 'bookstore.urls'
books/urls.py
urlpatterns = [
path('home/', create),
path('list/(?P<id>\d+)', list_view),
]
books/views.py
def create(request):
form = CreateForm(request.POST or None, request.FILES or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
messages.success(request, "Book Created")
return redirect('/books/list', kwargs={"id":instance.id})
return render(request, "home.html", {"form":form})
def list_view(request, id=None):
books = Book.objects.filter(id=id)
return render(request, "list.html", {"books": books})
Project Structure:
├── books
│ ├── admin.py
│ ├── forms.py
│ ├── __init__.py
│ ├── models.py
│ ├── urls.py
│ └── views.py
├── bookstore
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
Here is the screenshot -
EDIT - As addressed in the comments - Tried by appending / in the url expression of thebooks.urls but no luck :(
You are using the new path from Django 2.0 incorrectly. You shouldn't use a regex like \d+. Try changing it to:
path('list/<int:id>/', list_view, name='list_view'),
The name is required if you want to reverse the URL.
If you want to stick with regexes, then use re_path (or url() still works if you want to be compatible with older versions of Django). See the URL dispatcher docs for more info.
Note the trailing slash as well - otherwise your path matches http://192.168.0.106:8000/books/list/21 but not http://192.168.0.106:8000/books/list/21/.
I'm trying to code an e-phrasebook with Django to help people learn languages. Or actually a new version of an older one with new features. Anyway I'm badly stuck on the first meters here.
I have added some objects to the database and want to show them at the "categories" url. The first url http://127.0.0.1:8000/ works nicely and gives me a wonderful hello world. However, I need to connect the new app to the project, and when I try to open the url of the app http://127.0.0.1:8000/categories/, the browsers gives me this:
TypeError at /categories/
sequence item 0: expected str instance, Category found
My console complains about app's view.py, and within that about line 9 output = ', '.join(categories). I can't find anything wrong with it. Here is the whole views.py:
from django.http import HttpResponse
from django.shortcuts import render
from .models import Category
def category_list(request):
categories = Category.objects.all()
output = ', '.join(categories)
return HttpResponse(output)
This is the app's url.py:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.category_list),
]
Here is the main url.py:
from django.conf.urls import url, include
from django.contrib import admin
from . import views
urlpatterns = [
url(r'^categories/', include('phrasebooktwo.urls')),
url(r'^admin/', admin.site.urls),
url(r'^$', views.hello_world),
]
Here is the project tree:
bigboy_phrasebook
├── bigboy_phrasebook
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── settings.cpython-35.pyc
│ │ ├── urls.cpython-35.pyc
│ │ ├── views.cpython-35.pyc
│ │ └── wsgi.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
├── db.sqlite3
├── manage.py
└── phrasebooktwo
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-35.pyc
│ ├── admin.cpython-35.pyc
│ ├── models.cpython-35.pyc
│ ├── urls.cpython-35.pyc
│ └── views.cpython-35.pyc
├── admin.py
├── apps.py
├── migrations
│ ├── 0001_initial.py
│ ├── __init__.py
│ └── __pycache__
│ ├── 0001_initial.cpython-35.pyc
│ └── __init__.cpython-35.pyc
├── models.py
├── tests.py
├── urls.py
└── views.py
How do I get my categories page working? Thanks in advance for your help.
You have to use the str() or repr() or any other method which returns a string on the categories object before you use join(). Let me explain this by taking simple example:
class Category:
def __init__(self, name):
self.name = name
items = [Category('jam')]
out = ', '.join(items)
print(out)
If you run this code, you will get "TypeError: sequence item 0: expected str instance, Category found"
So, you have to modify the code as below:
class Category:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
items = [Category('jam').__str__()]
out = ', '.join(items)
print(out)
def category_list(request):
categories = Category.objects.all()
output = ', '.join(categories)
return HttpResponse(output)
Here categories is queryset object So when you add this join method it iterate as single instance from queryset and instance is objects of Model.So that will not work concat with join method. Use str method in join method like below way
def category_list(request):
categories = Category.objects.all()
output = ', '.join(str(categories))
return HttpResponse(output)
Ah, silly me. I was doing this based on a tutorial at www.teamtreehouse.com and I was sure that I had watched the whole video "First App View" but I had not. Sorry for the trouble people, and thanks for your help anyway! The teacher had intentionally written code that didn't work first, and then explained the right way to do it with this code, that in my own app looks like this:
def category_list(request):
categories = Category.objects.all()
output = ', '.join([str(category) for category in categories])
return HttpResponse(output)
Now it works. I have to remember to finish watching these videos in the future.
I have created a Django project foo.
├── manage.py
└── foo
├── __init__.py
├── settings.py
├── templates
│ ├── xyz.html
│ └── abc.html
├── tests.py
├── urls.py
├── views.py
└── wsgi.py
In views.py , I have created two class based view HomePage and ListPage
And routing configuration defined like this in urls.py:
urlpatterns = patterns('',
url(r'^$', HomePage.as_view() , name='home'),
url(r'^list$', ListPage.as_view(), name='list'),
# url(r'^admin/', include(admin.site.urls)),
)
Throws Error:
(InteractiveConsole)
>>> import django
>>> django.setup()
>>> from django.core.urlresolvers import resolve
>>> resolve('/')
ResolverMatch(func=<function HomePage at 0x7f77769bb9d8>, args=(), kwargs={}, url_name='home', app_name='None', namespace='')
>>> resolve('list')
Traceback (most recent call last):
File "<console>", line 1, in <module>
...
raise Resolver404({'path': path})
django.core.urlresolvers.Resolver404: {'path': 'list'}
What's going wrong here? Default root url '/' is resolving but 'list' is not resolving
This was a silly mistake of mine :). Though It might be helpful to somebody.
try
>>resolve('/list')
Hej! Many threads here had the same caption, but none of them solved my problem. I have a Django site an can access /admin (but it looks ugly). But on / there appears the following error page (DEBUG = True in settings.py):
TemplateDoesNotExist at /
index.html
Request Method: GET
Request URL: http://iecl.uni-potsdam.de/
Django Version: 1.4.5
Exception Type: TemplateDoesNotExist
Exception Value:
index.html
Exception Location: /usr/lib/python2.7/dist-packages/django/template/loader.py in find_template, line 138
Python Executable: /usr/bin/python
Python Version: 2.7.3
Python Path:
['/home/python/iecl/lib/python2.7/site-packages/distribute-0.6.28-py2.7.egg',
'/home/python/iecl/lib/python2.7/site-packages/pip-1.2.1-py2.7.egg',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-linux2',
'/usr/lib/python2.7/lib-tk',
'/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/pymodules/python2.7',
'/home/python/iecl/lib/python2.7/site-packages',
'/home/django/django']
Server time: Mon, 7 Apr 2014 11:28:46 +0200
Template-loader postmortem
Django tried loading these templates, in this order:
Using loader django.template.loaders.filesystem.Loader:
/home/django/django/templates/iecl_dev/index.html (File does not exist)
Using loader django.template.loaders.app_directories.Loader:
/usr/lib/python2.7/dist-packages/django/contrib/auth/templates/index.html (File does not exist)
/usr/lib/python2.7/dist-packages/django/contrib/admin/templates/index.html (File does not exist)
In fact, the file /home/django/django/templates/iecl_dev/index.html does exist and I also tried chmod o+r index.html without success.
The output of python iecl_dev/manage.py runserver 0.0.0.0:0 is
Validating models...
0 errors found
Django version 1.4.5, using settings 'iecl_dev.settings'
Development server is running at http://0.0.0.0:0/
Quit the server with CONTROL-C.
so everything seems fine here.
What perplexes me: The *.pyc files are created automatically when *.py files are run, right? After python iecl_dev/manage.py runserver 0.0.0.0:0 there is a file /home/django/django/iecl_dev/settings.pyc created. But it is not created, when I load the page in my web browser. Does that mean, the settings.py is never loaded? And how can Django say, a file, which exists, would not exist?
Edit¹:
My settings.py looks as follows:
import django.conf.global_settings as DEFAULT_SETTINGS
import os
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ADMINS = (
)
SETTINGS_PATH = os.path.realpath(os.path.dirname(__file__))
MANAGERS = ADMINS
DATABASES = { $
'default': { $
'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'iecl', # Or path to database file if using sqlite3.
'USER': 'iecl', # Not used with sqlite3.
'PASSWORD': '<xxx>', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3. $
'PORT': '', # Set to empty string for default. Not used with sqlite3.
}
}
TIME_ZONE = 'Europe/Berlin'
LANGUAGE_CODE = 'en-us'
SITE_ID = 1
USE_I18N = True
MEDIA_ROOT = '/var/www/django_media/iecl_dev/media/'
MEDIA_URL = ''
ADMIN_MEDIA_PREFIX = '/media/admin_media/'
SECRET_KEY = '<xxx>'
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
MIDDLEWARE_CLASSES = (
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
ROOT_URLCONF = 'iecl_dev.urls'
TEMPLATE_DIRS = (
os.path.join(SETTINGS_PATH, 'templates'),
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'iecl_dev.showStudents',
'django.contrib.admin',
)
TEMPLATE_CONTEXT_PROCESSORS = DEFAULT_SETTINGS.TEMPLATE_CONTEXT_PROCESSORS + (
)
Edit²:
The contents of `/home/django/django/` are as follows:
/home/django/django/:
iecl2
iecl_dev
templates
/home/django/django/iecl2:
__init__.py
__init__.pyc
manage.py
settings.py
settings.pyc
showStudents
urls.py
urls.pyc
/home/django/django/iecl2/showStudents:
__init__.py
__init__.pyc
admin.py
context_processors.py
models.py
models.pyc
views.py
views.pyc
/home/django/django/iecl_dev:
__init__.py
__init__.pyc
manage.py
piwik
settings.py
settings.pyc
showStudents
urls.py
urls.pyc
/home/django/django/iecl_dev/piwik:
__init__.py
app_settings.py
context_processors.py
models.py
tests.py
urls.py
views.py
/home/django/django/iecl_dev/showStudents:
__init__.py
__init__.pyc
admin.py
context_processors.py
models.py
models.pyc
views.py
/home/django/django/templates:
iecl
iecl_dev
/home/django/django/templates/iecl:
500.html
admin
changePW.html
editStudent.html
feedback.html
feedback_thanks.html
index.html
location.html
login.html
page.html
password_changed.html
showStudent.html
studentsOverview.html
/home/django/django/templates/iecl/admin:
404.html
500.html
actions.html
app_index.html
auth
base.html
base_site.html
change_form.html
change_list.html
change_list_results.html
date_hierarchy.html
delete_confirmation.html
delete_selected_confirmation.html
edit_inline
filter.html
includes
index.html
invalid_setup.html
login.html
object_history.html
pagination.html
prepopulated_fields_js.html
search_form.html
showStudents
submit_line.html
/home/django/django/templates/iecl/admin/auth:
user
/home/django/django/templates/iecl/admin/auth/user:
add_form.html
change_password.html
/home/django/django/templates/iecl/admin/edit_inline:
stacked.html
tabular.html
/home/django/django/templates/iecl/admin/includes:
fieldset.html
/home/django/django/templates/iecl/admin/showStudents:
pagecontent
userpagecontent
/home/django/django/templates/iecl/admin/showStudents/pagecontent:
change_form.html
/home/django/django/templates/iecl/admin/showStudents/userpagecontent:
change_form.html
/home/django/django/templates/iecl_dev:
500.html
__init__.py
admin
changePW.html
editStudent.html
feedback.html
feedback_thanks.html
index.html
location.html
login.html
page.html
password_changed.html
piwik
showStudent.html
studentsOverview.html
/home/django/django/templates/iecl_dev/admin:
404.html
500.html
actions.html
app_index.html
auth
base.html
base_site.html
change_form.html
change_list.html
change_list_results.html
date_hierarchy.html
delete_confirmation.html
delete_selected_confirmation.html
edit_inline
filter.html
includes
index.html
invalid_setup.html
login.html
object_history.html
pagination.html
prepopulated_fields_js.html
search_form.html
showStudents
submit_line.html
/home/django/django/templates/iecl_dev/admin/auth:
user
/home/django/django/templates/iecl_dev/admin/auth/user:
add_form.html
change_password.html
/home/django/django/templates/iecl_dev/admin/edit_inline:
stacked.html
tabular.html
/home/django/django/templates/iecl_dev/admin/includes:
fieldset.html
/home/django/django/templates/iecl_dev/admin/showStudents:
pagecontent
userpagecontent
/home/django/django/templates/iecl_dev/admin/showStudents/pagecontent:
change_form.html
/home/django/django/templates/iecl_dev/admin/showStudents/userpagecontent:
change_form.html
/home/django/django/templates/iecl_dev/piwik:
tracking.html
Edit³:
Ok. This is solved for me now. The solution was a conglomerate of different things. One of the problems was the missing rights. The user that executes Django, could not list the contents of the templates/ directory. chmod o+x templates/ did the job. Then there were some settings in the settings.py, that changed the place to look for the templates from templates/iecl_dev/ to iecl_dev/templates/. I saw this wrong path in the error message in my web browser. But simply reverting the settings.py to the old version, was not enough. Some service(s) needed to be restarted. I simply rebooted the machine and everything was fine. Miraculously, the /admin/ page now looks nice as well.
Many thanks for all your tips.
From what you've shown, I think you may have a problem with your project layout.
Usually, it is set as follows :
├── manage.py
├── yourproject
│ ├── __init__.py
│ ├── settings.py
│ ├── templates
│ ├── urls.py
│ ├── wsgi.py
│ └── wsgi.pyc
├── yourfirstapp
│ ├── __init__.py
│ ├── admin.py
│ ├── models.py
│ ├── templates
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── yoursecondapp
├── __init__.py
├── admin.py
├── models.py
├── templates
├── tests.py
├── urls.py
└── views.py
As you can see, each app inside your project can have it's own templates directory.yourproject is a bit particuliar, because it also stores unique files, such as settings.pyand wsgi.py. However, you can consider and use it as an app.
Now, if you want to use a template stored in yourproject/templates, you'll have to add yourproject to your INSTALLED_APPS settings.
Does it helps ? If not, can you edit your original post with your project layout ?
I wasted a lot of time trying to figure out what was wrong with my 'templates' directory and figured out :
You may have forgotten to add TEMPLATE_DIR in the following segment of settings.py :
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
So it should have 'DIRS': [TEMPLATE_DIR,], instead of 'DIRS': [],
The reason might be that django is trying to look for your templates directory in the directory with your setting.py file
Whereas actually the templates directory is in the parent directory.
Try doing something like this in your settings.py
SETTINGS_PATH = os.path.dirname(__file__)
PROJECT PATH = os.path.join(SETTINGS_PATH, os.pardir)
PROJECT_PATH = os.path.abspath(PROJECT_PATH)
TEMPLATES_PATH = os.path.join(PROJECT_PATH, "templates")
TEMPLATE_DIRS = (
TEMPLATES_PATH,
)
The error usually is due to incorrectly configured templates directory
I know this is late, but the solutions mentioned here did not work for me. So here is what works:
inside the settings.py file, add your appConfig in installed apps.
INSTALLED_APPS = [
'...',
'AppName.apps.AppNameConfig',
]
create a templates directory appName/templates/appName. (where appName is the name of your app).
When you call your render function, then you can pass it templates.name.html. Like so:
return render(request, 'templates/blog.html')