Django, tạo trang lỗi 500/404 tùy chỉnh


105

Làm theo hướng dẫn được tìm thấy chính xác ở đây , tôi không thể tạo trang lỗi 500 hoặc 404 tùy chỉnh. Nếu tôi nhập vào một url không hợp lệ, trang này sẽ cung cấp cho tôi trang lỗi mặc định. Có điều gì tôi nên kiểm tra để ngăn một trang tùy chỉnh hiển thị không?

Thư mục tệp:

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

trong mysite / settings.py tôi đã bật những điều này:

DEBUG = False
TEMPLATE_DEBUG = DEBUG

#....

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

trong 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'),
)

Tôi có thể đăng bất kỳ mã nào khác cần thiết, nhưng tôi nên thay đổi điều gì để nhận được trang lỗi 500 tùy chỉnh nếu tôi sử dụng url không hợp lệ?

Biên tập

GIẢI PHÁP: Tôi đã có một bổ sung

TEMPLATE_DIRS

trong settings.py của tôi và điều đó đã gây ra sự cố


1
Debug được thiết lập để False trong mã của tôi
Zac

Điều này có thể giúp bạn stackoverflow.com/a/12180499/1628832
karthikr

1
Tìm thấy câu trả lời này trong khi đang tìm cách chỉ tạo một mẫu tùy chỉnh và tôi muốn chia sẻ một chút tài liệu về Django đã giúp tôi rất nhiều; docs.djangoproject.com/en/1.7/ref/views/…
Blackeagle52

Của tôi hoạt động mà không có cài đặt template_dirs.
Programmingjoe

1
Điểm trớ trêu khi liên kết ở dòng đầu tiên dẫn đến trang 404 của Django. Tôi nghĩ là dẫn đến trang hướng dẫn cho một phiên bản Django không tồn tại. Đây là liên kết đến trang hướng dẫn cho Django 2.0: docs.djangoproject.com/en/2.0/intro/tutorial03
andrewec

Câu trả lời:


120

Dưới chính của bạn, hãy views.pythêm triển khai tùy chỉnh của riêng bạn của hai chế độ xem sau và chỉ cần thiết lập các mẫu 404.html500.html với những gì bạn muốn hiển thị.

Với giải pháp này, không cần thêm mã tùy chỉnh vào urls.py

Đây là mã:

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

Cập nhật

handler404handler500là các biến cấu hình chuỗi Django đã xuất được tìm thấy trong django/conf/urls/__init__.py. Đó là lý do tại sao cấu hình trên hoạt động.

Để cấu hình trên hoạt động, bạn nên xác định các biến sau trong urls.py tệp và trỏ các biến Django đã xuất vào đường dẫn chuỗi Python nơi các chế độ xem chức năng Django này được xác định, như sau:

# project/urls.py

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

Cập nhật cho Django 2.0

Chữ ký cho chế độ xem trình xử lý đã được thay đổi trong Django 2.0: https://docs.djangoproject.com/en/2.0/ref/views/#error-views

Nếu bạn sử dụng các dạng xem như trên, handler404 sẽ không thành công với thông báo:

"handler404 () có đối số từ khóa không mong muốn 'ngoại lệ'"

Trong trường hợp đó, hãy sửa đổi các quan điểm của bạn như thế này:

def handler404(request, exception, template_name="404.html"):
    response = render_to_response(template_name)
    response.status_code = 404
    return response

Điều này dường như hoạt động khá tốt đối với tôi, nhưng vì một số lý do mà request.user xuất hiện tốt trong mẫu 404, nhưng không phải ở mẫu 500 (và chúng gần như giống nhau) - đã đăng câu hỏi về điều này tại đây: stackoverflow.com/ câu hỏi / 26043211 /…
Gravity Grave

1
Một điều khác mà tôi băn khoăn - điều gì sẽ xảy ra nếu bạn sử dụng phần phụ trợ quản trị và muốn sử dụng các mẫu riêng biệt cho chúng? Theo hiểu biết của tôi, admin không có views.py để ghi đè lên và đặt bit này mã trong.
Trọng lực Grave

11
@GravityGrave 500 templatesẽ không hiển thị request.uservì nó đang báo lỗi máy chủ 500, vì vậy máy chủ không thể phục vụ bất kỳ thứ gì.
Aaron Lelevier

5
Không làm việc cho tôi với django 1,9; (Có lẽ tôi đang làm một cái gì đó sai là handler404 django tên dành riêng như thế nào sẽ django bí quyết rằng nó nên gọi chính xác điều đó xem.?
deathangel908

1
Tôi đã cập nhật câu trả lời dựa trên bình luận của bạn. Xin lỗi vì bản cập nhật quá muộn. Tôi hy vọng rằng điều này sẽ giúp.
Aaron Lelevier

71

Câu trả lời chính thức:

Đây là liên kết đến tài liệu chính thức về cách thiết lập chế độ xem lỗi tùy chỉnh:

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

Nó nói rằng hãy thêm những dòng như thế này vào URLconf của bạn (đặt chúng ở bất kỳ nơi nào khác sẽ không có tác dụng):

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'

Bạn cũng có thể tùy chỉnh chế độ xem lỗi CSRF bằng cách sửa đổi cài đặt CSRF_FAILURE_VIEW .

Trình xử lý lỗi mặc định:

Nó đáng đọc tài liệu của các trình xử lý lỗi mặc định, page_not_found, server_error, permission_deniedbad_request. Theo mặc định, họ sử dụng những mẫu này nếu họ có thể tìm thấy chúng, tương ứng: 404.html, 500.html, 403.html, và400.html .

Vì vậy, nếu tất cả những gì bạn muốn làm là tạo ra các trang lỗi khá lớn, chỉ cần tạo các tệp đó trong TEMPLATE_DIRS thư mục, bạn không cần chỉnh sửa URLConf gì cả. Đọc tài liệu để xem những biến ngữ cảnh nào có sẵn.

Trong Django 1.10 trở lên, chế độ xem lỗi CSRF mặc định sử dụng mẫu 403_csrf.html.

Gotcha:

Đừng quên rằng DEBUGphải được đặt thành False để chúng hoạt động, nếu không, các trình xử lý gỡ lỗi bình thường sẽ được sử dụng.


1
Tôi đã thêm, nhưng nó không hoạt động. Thêm handler404 và những người khác trỏ đến đúng địa điểm trong quan điểm của tôi, nhưng nó không làm việc, vẫn thấy mặc định 404. Và vâng, tôi đang ở trong chế độ False Debug và sử dụng 1,9
KhoPhi

Sử dụng Django 1.9 và chỉ cần thêm 500.html các mẫu, v.v. sẽ hiển thị chúng thay vì các trang tiêu chuẩn. Dễ dàng sửa chữa.
curtisp

2
Gotcha đã giúp tôi. Nó hoạt động bằng cách thực hiện những thay đổi này trong settings.py, đặt DEBUG = False và ALLOWED_HOSTS = ['0.0.0.0'] để chấp nhận yêu cầu http từ bất kỳ khách hàng nào.
shaffooo

1
Chỉ trong trường hợp bất cứ ai khác đang tự hỏi nơi trên trái đất là URLconf, ở đây nó là
Arthur Tarasov

38

Thêm những dòng này trong 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'

# ...

và triển khai các chế độ xem tùy chỉnh của chúng tôi trong 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

# ...

5
Tại sao bạn handler400chỉ nhập để ghi đè lên nó handler400 = 'myapp.views.bad_request'?
Flimm


5
Bạn không cần nhập các trình xử lý ở đây để ghi đè chúng.
funkotron

1
Bạn không nên sử dụng render_to_response. Từ tài liệu: "nó không được khuyến khích và có khả năng không được dùng nữa trong tương lai."
Timmy O'Mahony

Đối với Django 1.10, render_to_responsesẽ không được dùng nữa, hãy xem phần sau (sử dụng renderthay thế): stackoverflow.com/questions/44228397/…
mrdaliri,

21

Từ trang bạn đã tham khảo:

Khi bạn nâng Http404 từ trong một chế độ xem, Django sẽ tải một chế độ xem đặc biệt dành cho việc xử lý lỗi 404. Nó tìm thấy nó bằng cách tìm kiếm biến handler404 trong URLconf gốc của bạn (và chỉ trong URLconf gốc của bạn; thiết lập handler404 ở bất kỳ nơi nào khác sẽ không có hiệu lực), là một chuỗi trong cú pháp có dấu chấm của Python - cùng định dạng mà các lệnh gọi lại URLconf bình thường sử dụng. Bản thân chế độ xem 404 không có gì đặc biệt: Nó chỉ là một chế độ xem bình thường.

Vì vậy, tôi tin rằng bạn cần thêm một cái gì đó như thế này vào urls.py:

handler404 = 'views.my_404_view'

và tương tự cho handler500.


Trông như thế nào Mike? Hôm nay là ngày đầu tiên tôi sử dụng Django và tôi vẫn treo lên những sợi dây thừng
Zac

2
@JimRilye Bạn sẽ cần thêm một hàm 500 phù hợp vào chế độ xem của mình, sau đó tham chiếu nó với biến đó. Vì vậy, phía trên urlpatterns = ...dòng của bạn , hãy thêm một dòng có nội dung handler500 = 'views.handle500', sau đó thêm một def handle500(request):vào views.py hiển thị 500.html của bạn.
Mike Pelley,

18

Nếu tất cả những gì bạn cần là hiển thị các trang tùy chỉnh có một số thông báo lỗi lạ cho trang web của bạn khi nào DEBUG = False, thì hãy thêm hai mẫu có tên 404.html và 500.html vào thư mục mẫu của bạn và nó sẽ tự động chọn các trang tùy chỉnh này khi có 404 hoặc 500 được nuôi dưỡng.


1
Điều này hoạt động chỉ cần đảm bảo rằng bạn có một cái gì đó như: 'DIRS': [os.path.join(BASE_DIR, '<project_name>/templates')]trong danh sách TEMPLATES của bạn trong settings.py.
eric

12

Trong Django 2. * bạn có thể sử dụng cấu trúc này trong views.py

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

Trong settings.py

DEBUG = False

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

if DEBUG is True:
    ALLOWED_HOSTS = []

Trong urls.py

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

Thông thường, tôi tạo default_app và xử lý các lỗi trên toàn trang web, bộ xử lý ngữ cảnh trong đó.


Làm việc cho tôi. Nhưng cái gì là exception?
zeleven

Theo link tài liệu: docs.djangoproject.com/en/2.1/ref/urls/… . Nó được viết: hãy đảm bảo trình xử lý chấp nhận các đối số yêu cầu và ngoại lệ
Alouani Younes 12/1218

1
Làm việc cho tôi trong Django 3.0 . Nhưng là locals()gì? Tệp chỉ hiển thị pass.
mê hoặc

9

settings.py:

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

và chỉ cần thêm của bạn 404.html500.htmlcác trang trong thư mục mẫu. loại bỏ 404.html500.htmlkhỏi các mẫu trong ứng dụng thăm dò ý kiến.


Cách sử dụng thông báo của raise Http404('msg'): stackoverflow.com/a/37109914/895245 {{ request_path }} cũng có sẵn.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功


7

Tạo lỗi, Trên trang lỗi, hãy tìm ra nơi django đang tải các mẫu, ý tôi là ngăn xếp đường dẫn. Trong cơ sở template_dir, hãy thêm các trang html này vào 500.html , 404.html . Khi những lỗi này xảy ra, các tệp mẫu tương ứng sẽ được tải tự động.

Bạn cũng có thể thêm các trang cho các mã lỗi khác, như 400403 .

Hy vọng điều này giúp đỡ !!!


6

Trong Django 3.x, câu trả lời được chấp nhận sẽ không hoạt động vìrender_to_response đã bị xóa hoàn toàn cũng như một số thay đổi khác đã được thực hiện kể từ phiên bản mà câu trả lời được chấp nhận hoạt động.

Một số câu trả lời khác cũng có ở đó nhưng tôi trình bày một câu trả lời rõ ràng hơn một chút:

Trong urls.pytệp chính của bạn :

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

Trong yourapp/views.pyhồ sơ:

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

Đảm bảo rằng bạn đã nhập render()vào yourapp/views.pytệp:

from django.shortcuts import render

Lưu ý phụ: render_to_response()không được dùng trong Django 2.xvà nó đã bị xóa hoàn toàn 3.x.


5

Dưới dạng một dòng duy nhất (cho trang chung chung 404):

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)

1
Và sử dụng nó ở đâu?
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' 

Điều này hoạt động trên django 2.0

Đảm bảo bao gồm tùy chỉnh của bạn 404.htmlbên trong thư mục mẫu ứng dụng.


4

Django 3.0

đây là liên kết cách tùy chỉnh chế độ xem lỗi

đây là liên kết làm thế nào để hiển thị một chế độ xem

trong urls.py(cái chính, trong thư mục dự án), đặt:

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'

và trong ứng dụng đó ( my_app_name) đặt 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", {})

LƯU Ý: error/404.htmllà đường dẫn nếu bạn đặt tệp của mình vào thư mục mẫu của dự án (không phải ứng dụng), templates/errors/404.htmlvì vậy hãy đặt tệp ở nơi bạn muốn và viết đúng đường dẫn.

LƯU Ý 2: Sau khi tải lại trang, nếu bạn vẫn thấy mẫu cũ, hãy thay đổi settings.py DEBUG=True, lưu mẫu và sau đó lại vào False(để khởi động lại máy chủ và thu thập các tệp mới).


Lưu ý thêm: Nếu bạn đang chạy trong DEUB=Falsecác tệp tĩnh của bạn có thể không được phân phát, khiến bạn không thể xem trước các thay đổi mẫu lỗi tùy chỉnh của mình. Sử dụng ./manage.py runserver --insecuređể bắt buộc django phục vụ họ.
Rob


3

Hãy thử chuyển các mẫu lỗi của bạn sang .../Django/mysite/templates/ ?

Tôi lưu ý chắc chắn về điều này, nhưng tôi nghĩ rằng những điều này cần phải "toàn cầu" cho trang web.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.