HttpRequest
所有的View function(有跟某URL對應的函式)都應該以HttpRequest
物件作為第一個參數。這是因為HttpRequest
物件(之後會以request代稱HttpRequest)含有關於本次web request及使用者的重要資訊,所以,沒有request
,我們對於使用者的情況和需求以及提供的資訊會一無所知。
URL訊息:
下面範例將介紹request
包含了哪些有用的URL訊息.
# mysite/restaurants/menu.html
# 以上略...
<body>
<p>您現在的位置在{{ path }}</p> # 加入本行
{% for r in restaurants %}
<h2>{{ r.name }}</h2>
{% if r.food_set.all %}
<p>本餐廳共有{{ r.food_set.all|length }}道菜</p>
# 以下略...
我們看到在模版上多出了一個{{ path }}變量,我們必須在視圖函式中準備好該變量:
# mysite/restaurants/views.py
# 以上略...
def menu(request):
path = request.path # 加入本行
restaurants = Restaurant.objects.all()
return render_to_response('menu.html',locals())
會發現在首行出現了位置的資訊,request就是知道這些!如果你需要提示使用者在哪個位置,就不需要將位置資訊寫死到模版中了,透過request.path我們可以知道除了網域名稱以外的請求路徑。
META
request物件裡面還有一個記錄header訊息的字典,叫做META,無論是使用者瀏覽器的資訊或是客戶端的IP位址,都可以查詢的到。要把資料列印出來的方法很簡單,先設定url對應,再撰寫視圖函式.
Ex.
def meta(request):
values = request.META.items() # 將字典的鍵值對抽出成為一個清單
values.sort() # 對清單進行排序
html = []
for k, v in values:
html.append('<tr><td>{0}</td><td>{1}</td></tr>'.format(k, v))
return HttpResponse('<table>{0}</table>'.format('\n'.join(html)))
GET與POST
這兩個方法負責提交使用者表單的數據,表現上的差別在:GET方法會透過在請求路徑後面添增查詢字符來提交數據,而POST方法是隱性地傳送數據的鍵值對.兩者在請求上的不同:
GET www.restaurants.com/restaurant/?id=1
POST www.restaurants.com/restaurant
這使得POST方法更適合拿來做資訊需隱密的請求,而GET方法則能漂亮的提供一個查詢相同頁面的URL(每次使用這個URL總是能獲得一個id=1的頁面,POST方法可能就不行了),GET方法適合用來取得數據和對應的頁面,POST方法適合利用提交數據去更動資料庫.
這兩個方法所提交的數據都會以鍵值對的方式儲存於request物件中,分別存於request.GET
和request.POST
,分別都是一個類似於字典的物件。
在這邊我們要將之前建立的Model顯示在網頁上.
# Dinbendon/urls.py
...
url(r'^store/$', store_list, name='store_list'),
...
利用stores = Store.objects.all()
取出所有的 store objects 後,在 render 的最後面增加一個參數。這個參數為 render 提示了額外的 context data,可以在處理 template 時使用。
# stores/views.py
#...
from .models import Store
def store_list(request):
stores = Store.objects.all()
return render(request, 'store_list.html', {'stores': stores})
#...
template tags for 與 endfor。這是 Django templates 中表示迴圈的方法。在 templates 裡沒辦法用縮排表示階層,所以我們是用一個 endfor 標籤來標示迴圈結束。取用物件內 attributes 的方法仍然是用一個點,不過我們必須在旁邊加上兩組大括弧,來標注這是 template 語法,而不是真的要在 HTML 中印出 store.name 這個字串。
{# stores/templates/store_list.html #}
<!DOCTYPE html>
<html>
<head>
<title>店家列表 | 午餐系統</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body>
<nav class="navbar navbar-default navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="{% url 'home' %}">午餐系統</a>
</div>
</div>
</nav>
<div class="container">
{% for store in stores %}
<div class="store">
<h2>{{ store.name }}</h2>
<p>{{ store.notes }}</p>
</div>
{% endfor %}
</div>
</body>
</html>
執行runserver,在http://..../store/
中會出現我們原本在/admin
中增加的store.
新增每個store的獨立頁面
第一步:如何把網址對應到合適的頁面。Django 的做法就是用 capturing groups,pk
在這裡指 primary key
# Dinbendon/urls.py
...
url(r'^store/(?P<pk>\d+)/$', store_detail, name='store_detail'), # 新增這行
url(r'^admin/', include(admin.site.urls)),
)
# stores/views.py
from django.http import Http404
def store_detail(request, pk):
try:
store = Store.objects.get(pk=pk)
except Store.DoesNotExist:
raise Http404
return render(request, 'store_detail.html', {'store': store})
<!DOCTYPE html>
<html>
<head>
<title>{{ store.name }} | 午餐系統</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body>
<nav class="navbar navbar-default navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="{% url 'home' %}">午餐系統</a>
</div>
</div>
</nav>
<div class="container">
<h1>{{ store.name }}</h1>
<p>{{ store.notes }}</p>
<table class="table">
<thead>
<tr><th>品項</th><th>單價</th></tr>
</thead>
<tbody>
{% for item in store.menu_items.all %}
<tr><td>{{ item.name }}</td><td>{{ item.price }}</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
另外在store_list.html
中 的 <h2>
那行改成這樣:
<h2><a href="{% url 'store_detail' pk=store.pk %}">{{ store.name }}</a></h2>
使用 url tag,不過這次除了 name 之外多加了一個參數。這裡傳入的參數會被用在 URL 的 capturing group 上,所以這樣就可以得到某個 store 的 URL!
執行runserver:
參考:
http://dokelung-blog.logdown.com/posts/220833-django-notes-7-forms
沒有留言:
張貼留言