iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 21
0

繼 Day20 ,透過path的設定,我們現在有了更多的網頁

但是在實作上,可能會因為找不到該網站而發生錯誤,因此我們在撰寫程式的同時,也要考量到發生例外的狀況,因此 Day20 的程式碼還需要改良

而當我們在瀏覽網頁的同時,若是該網頁不存在,就會發生 HTTP 404

對於這方面的處理,Django提供了一個方便的方法,能夠讓我們處理發生 HTTP 404 的問題

因此 Day20 的 singleVendor 函式 要修改成如下

# 額外 import Http404
from django.http import Http404

def singleVendor(request, id):
    try:
        vendor_list = Vendor.objects.get(id=id)
    except Vendor.DoesNotExist:
        raise Http404
    context = {
        'vendor_list': vendor_list
    }
    return render(request, 'vendors/vendor_detail.html', context)

如此一來就能夠正常的顯示HTTP 404
https://ithelp.ithome.com.tw/upload/images/20181021/20111829dwcbc013cj.jpg
不過這跟實際上看到的 404 還是不一樣,因為 Django 目前還處在 Debug 的模式,也就是說你能夠在 settings.py 看到這個設定

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

因此我們要去修改 Debug 模式

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

不過同時,你也要將允許的網域加在 settings.py 的 ALLOWED_HOSTS,這裡因為只要測試功能,所以我們可以改成這樣,所以實際上的設定值就要取決於你的網站而做設定囉!

ALLOWED_HOSTS = ['*']

接著再來看網頁的話,你就可以看到正常的 HTTP 404 頁面
https://ithelp.ithome.com.tw/upload/images/20181021/20111829u7WThioLGn.jpg

因此當網頁要上線的時候,務必要將 Debug模式 關掉呀!!
ALLOWED_HOSTS = ['*']是個壞榜樣 好孩子不要亂學

但是我們也一直強調了,Django 的中心思想就是 DRY (Don't Repeat Yourself),因此 Django 另外還提供了一個更方便的方法 get_object_or_404

從字面上,我們就可以知道它的意思就是

  • 取得一個物件 否則
  • 觸發 HTTP 404

也就是說,你能夠將程式碼修改成這樣

from django.shortcuts import get_object_or_404 # 新增

def singleVendor(request, id):
    vendor_list = get_object_or_404(Vendor, id=id)
    # try:
    #     vendor_list = Vendor.objects.get(id=id)
    # except Vendor.DoesNotExist:
    #     raise Http404
    context = {
        'vendor_list': vendor_list
    }
    return render(request, 'vendors/vendor_detail.html', context)

如此一來 Django 就幫你完成了例外處理的工作,勢必幫你在開發上省掉很多這種例外的時間呢! ^^

當然你有時間,也別忘了去看看 get_object_or_404 的原始碼 ( 增廣見聞

def get_object_or_404(klass, *args, **kwargs):
    """
    Use get() to return an object, or raise a Http404 exception if the object
    does not exist.

    klass may be a Model, Manager, or QuerySet object. All other passed
    arguments and keyword arguments are used in the get() query.

    Like with QuerySet.get(), MultipleObjectsReturned is raised if more than
    one object is found.
    """
    queryset = _get_queryset(klass)
    if not hasattr(queryset, 'get'):
        klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__
        raise ValueError(
            "First argument to get_object_or_404() must be a Model, Manager, "
            "or QuerySet, not '%s'." % klass__name
        )
    try:
        return queryset.get(*args, **kwargs)
    except queryset.model.DoesNotExist:
        raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)

若是你今天要處理的並不只是一個物件, Django 也有幫你準備 get_list_or_404

而你可以很容易就理解兩者之間的差異

  • get_object_or_404 : 透過 get 取得一個物件
  • get_list_or_404 : 透過 filter 取得一些物件

今日小節

今天帶大家了解,Django 如何在撰寫網頁時,更方便地處理這一些例外,而在使用這些好用的函式時,有空去追個 code也是一件相當有趣的事情^^

今天介紹到這邊,我們明天見

祈福 台鐵乘客 及 救難國軍 平安


上一篇
Day20 : 動態網址 - path 應用
下一篇
Day22 : Django urls name
系列文
From Django 1.11 to Django 2.1 30

尚未有邦友留言

立即登入留言