Django, membuat halaman kesalahan 500/404 tersuai

105

Tepat mengikuti tutorial yang ditemukan di sini , saya tidak dapat membuat halaman kesalahan 500 atau 404 kustom. Jika saya mengetikkan url yang buruk, halaman tersebut memberi saya halaman kesalahan default. Apakah ada hal yang harus saya periksa yang akan mencegah halaman kustom muncul?

Direktori file:

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

dalam mysite / settings.py Saya telah mengaktifkan ini:

DEBUG = False
TEMPLATE_DEBUG = DEBUG

#....

TEMPLATE_DIRS = (
    'C:/Users/Me/Django/mysite/templates', 
)

dalam situs saya / 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'),
)

Saya dapat memposting kode lain yang diperlukan, tetapi apa yang harus saya ubah untuk mendapatkan halaman kesalahan 500 kustom jika saya menggunakan url yang buruk?

Edit

SOLUSI: Saya punya tambahan

TEMPLATE_DIRS

dalam my settings.py dan itu yang menyebabkan masalah

Zac
sumber
1
Debug disetel ke False dalam kode saya
Zac
Ini dapat membantu Anda stackoverflow.com/a/12180499/1628832
karthikr
1
Menemukan jawaban ini ketika mencari cara untuk membuat hanya cetakan kustom dan saya ingin berbagi sedikit dokumentasi Django yang banyak membantu saya; docs.djangoproject.com/en/1.7/ref/views/…
Blackeagle52
Milik saya bekerja tanpa pengaturan template_dirs.
Programmingjoe
1
Poin ironi ketika tautan di baris pertama mengarah ke halaman 404 Django. Mengarah ke halaman tutorial untuk versi Django yang tidak ada saya kira. Ini adalah tautan ke halaman tutorial untuk Django 2.0: docs.djangoproject.com/en/2.0/intro/tutorial03
andrewec

Jawaban:

120

Di bawah utama Anda, views.pytambahkan implementasi kustom Anda sendiri dari dua tampilan berikut, dan cukup siapkan template 404.html dan 500.html dengan apa yang ingin Anda tampilkan.

Dengan solusi ini, tidak ada kode khusus yang perlu ditambahkan ke urls.py

Berikut kodenya:

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

Memperbarui

handler404dan handler500diekspor variabel konfigurasi string Django ditemukan di django/conf/urls/__init__.py. Itulah mengapa konfigurasi di atas berfungsi.

Untuk membuat konfigurasi di atas bekerja, Anda harus mendefinisikan variabel berikut dalam urls.pyberkas Anda dan mengarahkan variabel Django yang diekspor ke jalur Python string di mana tampilan fungsional Django ini didefinisikan, seperti:

# project/urls.py

handler404 = 'my_app.views.handler404'
handler500 = 'my_app.views.handler500'

Pembaruan untuk Django 2.0

Tanda tangan untuk tampilan penangan diubah di Django 2.0: https://docs.djangoproject.com/en/2.0/ref/views/#error-views

Jika Anda menggunakan tampilan seperti di atas, handler404 akan gagal dengan pesan:

"handler404 () mendapat 'pengecualian' argumen kata kunci yang tidak terduga"

Dalam kasus seperti itu, ubah pandangan Anda seperti ini:

def handler404(request, exception, template_name="404.html"):
    response = render_to_response(template_name)
    response.status_code = 404
    return response
Aaron Lelevier
sumber
Ini tampaknya bekerja cukup baik bagi saya, tetapi untuk beberapa alasan request.user tampak baik-baik saja di templat 404, tetapi tidak sama sekali di templat 500 (dan mereka hampir identik) - memposting pertanyaan tentang ini di sini: stackoverflow.com/ pertanyaan / 26043211 /…
Gravity Grave
1
Hal lain yang saya ingin tahu - bagaimana jika Anda menggunakan backend admin dan ingin menggunakan template terpisah untuk itu? Sepengetahuan saya, admin tidak memiliki views.py untuk ditimpa dan memasukkan sedikit kode ini.
Gravity Grave
11
@GravityGrave 500 templatetidak akan merender request.userkarena melaporkan kesalahan server 500, sehingga server tidak dapat menyajikan apa pun.
Aaron Lelevier
5
Tidak berhasil untuk saya dengan django 1.9; (Mungkin saya melakukan sesuatu yang salah. Apakah nama handler404 django sudah dipesan? Bagaimana django tahu bahwa ia harus memanggil tampilan seperti itu?
deathangel908
1
Saya memperbarui jawaban berdasarkan komentar Anda. Maaf update terlambat. Saya harap ini membantu.
Aaron Lelevier
71

Jawaban resmi:

Berikut ini tautan ke dokumentasi resmi tentang cara mengatur tampilan kesalahan khusus:

https://docs.djangoproject.com/en/stable/topics/http/views/#customizing-error-views

Dikatakan untuk menambahkan baris seperti ini di URLconf Anda (mengaturnya di tempat lain tidak akan berpengaruh):

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'

Anda juga dapat menyesuaikan tampilan kesalahan CSRF dengan mengubah pengaturan CSRF_FAILURE_VIEW.

Penangan kesalahan default:

Itu layak membaca dokumentasi dari penangan error default, page_not_found, server_error, permission_denieddan bad_request. Secara default, mereka menggunakan template ini jika mereka dapat menemukan mereka, masing-masing: 404.html, 500.html, 403.html, dan 400.html.

Jadi jika yang ingin Anda lakukan hanyalah membuat halaman error yang cantik, cukup buat file-file itu di TEMPLATE_DIRSdirektori, Anda tidak perlu mengedit URLConf sama sekali. Baca dokumentasi untuk melihat variabel konteks mana yang tersedia.

Dalam Django 1.10 dan yang lebih baru, tampilan kesalahan CSRF default menggunakan templat 403_csrf.html.

Kena kau:

Jangan lupa bahwa DEBUGharus disetel ke False agar ini berfungsi, jika tidak, penangan debug normal akan digunakan.

Flimm
sumber
1
Saya memang menambahkan, tetapi tidak berhasil. Menambahkan handler404 dan lainnya yang menunjuk ke tempat yang tepat dalam pandangan saya, namun tidak berhasil, masih melihat default 404. Dan ya, saya dalam mode Debug False dan menggunakan 1.9
KhoPhi
Menggunakan Django 1.9 dan hanya menambahkan templat 500.html dll menunjukkan mereka alih-alih halaman standar. Perbaikan mudah yang bagus.
menskors
2
Gotcha membantu saya. Ini bekerja dengan membuat perubahan ini di my settings.py, set DEBUG = False dan ALLOWED_HOSTS = ['0.0.0.0'] untuk menerima permintaan http dari klien mana pun.
shaffooo
1
Untuk berjaga-jaga jika ada orang lain yang bertanya-tanya di mana letak URLconf, ini dia
Arthur Tarasov
38

Tambahkan baris-baris ini di 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'

# ...

dan menerapkan tampilan ubahsuaian kami di 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

# ...
Armance
sumber
5
Mengapa Anda mengimpor handler400hanya untuk menimpanya handler400 = 'myapp.views.bad_request'?
Flimm
5
Anda tidak perlu mengimpor penangan di sini untuk menimpanya.
funkotron
1
Anda tidak boleh menggunakan render_to_response. Dari dokumen: "ini tidak disarankan dan kemungkinan besar akan dihentikan di masa mendatang."
Timmy O'Mahony
Untuk Django 1.10, seperti render_to_responseyang akan ditinggalkan, lihat berikut ini (gunakan rendersebagai gantinya): stackoverflow.com/questions/44228397/…
mrdaliri
21

Dari halaman yang Anda referensikan:

Ketika Anda menaikkan Http404 dari dalam sebuah tampilan, Django akan memuat tampilan khusus yang ditujukan untuk menangani kesalahan 404. Ia menemukannya dengan mencari variabel handler404 di root URLconf Anda (dan hanya di root URLconf Anda; pengaturan handler404 di tempat lain tidak akan berpengaruh), yang merupakan string dalam sintaks bertitik Python - format yang sama dengan yang digunakan oleh callback URLconf normal. Tampilan 404 sendiri tidak ada yang istimewa: Ini hanya tampilan biasa.

Jadi saya yakin Anda perlu menambahkan sesuatu seperti ini ke urls.py Anda:

handler404 = 'views.my_404_view'

dan serupa untuk handler500.

Mike Pelley
sumber
Bagaimana Mike terlihat? Hari ini adalah hari pertama saya menggunakan Django dan saya masih bergantung pada tali
Zac
2
@JimRilye Anda harus menambahkan fungsi 500 yang sesuai ke tampilan Anda, lalu mereferensikannya dengan variabel itu. Jadi, di atas urlpatterns = ...baris Anda , tambahkan baris yang bertuliskan handler500 = 'views.handle500', lalu tambahkan a def handle500(request):ke views.py Anda yang menampilkan 500.html Anda.
Mike Pelley
18

Jika yang Anda butuhkan hanyalah menampilkan halaman khusus yang memiliki beberapa pesan kesalahan mewah untuk situs Anda saat itu DEBUG = False, maka tambahkan dua templat bernama 404.html dan 500.html di direktori templat Anda dan secara otomatis akan mengambil halaman khusus ini ketika 404 atau 500 dibesarkan.

Krishna G Nair
sumber
1
Ini berfungsi, pastikan Anda memiliki sesuatu seperti: 'DIRS': [os.path.join(BASE_DIR, '<project_name>/templates')]dalam daftar TEMPLAT Anda di settings.py.
eric
12

Dalam Django 2. * Anda dapat menggunakan konstruksi ini dalam views.py

def handler404(request, exception):
    return render(request, 'errors/404.html', locals())

Di settings.py

DEBUG = False

if DEBUG is False:
    ALLOWED_HOSTS = [
        '127.0.0.1:8000',
        '*',
    ]

if DEBUG is True:
    ALLOWED_HOSTS = []

Di urls.py

# https://docs.djangoproject.com/en/2.0/topics/http/views/#customizing-error-views
handler404 = 'YOUR_APP_NAME.views.handler404'

Biasanya saya membuat default_app dan menangani kesalahan di seluruh situs, prosesor konteks di dalamnya.

Sarang
sumber
Bekerja untuk saya. Tapi apa itu exception?
zeleven
Menurut tautan dokumentasi: docs.djangoproject.com/en/2.1/ref/urls/… . Ada tertulis: pastikan pawang menerima argumen permintaan dan pengecualian
Alouani Younes
1
Bekerja untuk saya di Django 3.0 . Tapi apa itu locals()? File hanya menunjukkan pass.
enchance
9

settings.py:

DEBUG = False
TEMPLATE_DEBUG = DEBUG
ALLOWED_HOSTS = ['localhost']  #provide your host name

dan tambahkan saja Anda 404.htmldan 500.htmlhalaman di folder template. hapus 404.htmldan 500.htmldari templat di aplikasi jajak pendapat.

Rakesh babu
sumber
Cara menggunakan pesan dari raise Http404('msg'): stackoverflow.com/a/37109914/895245 {{ request_path }} juga tersedia.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
TEMPLATE_DEBUG dihapus dari django2 docs.quantifiedcode.com/python-anti-patterns/django/1.8/…
Steve W
7

Buat kesalahan, Pada halaman kesalahan cari tahu dari mana django memuat template. Maksud saya adalah jalur tumpukan. Dalam basis template_dir tambahkan halaman html ini 500.html , 404.html . Jika kesalahan ini terjadi, file template masing-masing akan dimuat secara otomatis.

Anda juga dapat menambahkan halaman untuk kode kesalahan lain, seperti 400 dan 403 .

Semoga bantuan ini !!!

allsyed
sumber
6

Di Django 3.x, jawaban yang diterima tidak akan bekerja karena render_to_responsetelah dihapus seluruhnya serta beberapa perubahan lagi telah dibuat sejak versi jawaban yang diterima bekerja untuk.

Beberapa jawaban lain juga ada di sana tetapi saya menyajikan jawaban yang sedikit lebih bersih:

Di urls.pyfile utama Anda :

handler404 = 'yourapp.views.handler404'
handler500 = 'yourapp.views.handler500'

Dalam yourapp/views.pyfile:

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

Pastikan Anda telah mengimpor render()dalam yourapp/views.pyfile:

from django.shortcuts import render

Catatan tambahan: render_to_response()tidak digunakan lagi di Django 2.xdan telah dihapus seluruhnya dalam verisi 3.x.

Rehmat
sumber
5

Sebagai satu baris (untuk 404 halaman generik):

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)
FireZenk
sumber
1
Dan di mana menggunakannya?
Sami
4
# 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' 

Ini bekerja pada django 2.0

Pastikan untuk memasukkan kustom Anda 404.htmldi dalam folder template aplikasi.

ENDEESA
sumber
4

Django 3.0

di sini adalah tautan cara menyesuaikan tampilan kesalahan

berikut adalah link bagaimana membuat view

di urls.py(yang utama, di folder proyek), letakkan:

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'

dan di app itu ( my_app_name) letakkan di 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", {})

CATATAN: error/404.htmladalah jalur jika Anda menempatkan file Anda ke dalam folder template proyek (bukan aplikasi) templates/errors/404.htmljadi harap letakkan file di tempat yang Anda inginkan dan tulis jalur yang benar.

CATATAN 2: Setelah halaman dimuat ulang, jika Anda masih melihat template lama, ubah settings.py DEBUG=True, simpan, dan kemudian lagi ke False(untuk memulai ulang server dan mengumpulkan file baru).

elano7
sumber
Catatan tambahan: Jika Anda menjalankan DEUB=Falsefile statis Anda mungkin tidak dilayani, sehingga Anda tidak dapat melihat perubahan template kesalahan kustom Anda. Gunakan ./manage.py runserver --insecureuntuk memaksa django untuk melayani mereka.
Rob
3

Coba pindahkan template kesalahan Anda ke .../Django/mysite/templates/?

Saya yakin tentang yang satu ini, tetapi saya pikir ini harus "global" ke situs web.

astrognocci.dll
sumber