004---設計新增和編輯書籍頁面
阿新 • • 發佈:2018-11-09
現在就來新增書籍吧。為他設計一條url。
1 path('book_add/', views.book_add, name='book_add'), # 走bood_add檢視函式
別忘了更改index.html新增書籍的這條a標籤。
<a href="{% url 'book_add' %}" class="btn btn-default" style="margin-top:10px;margin-bottom: 10px">新增書籍</a>
新增書籍,代表要提交資料,所以form表單是少不了的。
而且,新增書籍還要為他新增與其對應的出版社,作者。所以檢視就要獲取所有出版社,作者,渲染到book_add.html頁面。
檢視部分:
1 def book_add(request):
2 pub_lt = Publish.objects.all() # 資料庫獲取所有出版社
3 author_lt = Author.objects.all() # 資料庫獲取所有作者
4 return render(request, 'book_add.html', {"pub_list": pub_lt, "author_list": author_lt})
模版部分(book_add.html):
1 {% extends 'base.html' %}
2
3 {% block title %}
4 <title>新增書籍</title>
5 {% endblock %}
6
7 {% block body %}
8 <h3>新增書籍</h3>
9 {% include 'form.html' %}
10 {% endblock %}
也許你會感到奇怪,為什麼新增頁面這麼少程式碼。沒錯、就是這麼少。因為用到了繼承base.html。我只要寫個form表單就行。可這也沒看到form表單,因為後面圖書還有個編輯頁面。其實也是form表單。所以
這裡有用到了抽取模版。把form表單抽取出來,使用的話是{% include 'form.html' %}。代表把form.html拿到這來。
模版部分(form.html):
1 <form action="" method="post">
2 {% csrf_token %}
3 <div class="form-group">
4 <label for="title">書籍名稱</label>
5 <input type="text" name="title" class="form-control" id="title" value="{{ book.title }}">
6 </div>
7 <div class="form-group">
8 <label for="price">價格</label>
9 <input type="text" name="price" id="price" class="form-control" value="{{ book.price }}">
10 </div>
11 <div class="form-group">
12 <label for="pub_date">出版日期</label>
13 <input type="date" name="pub_date" class="form-control" id="pub_date" value="{{ book.pub_date|date:"Y-m-d" }}">
14 </div>
15 <div class="form-group">
16 <label for="">出版社</label>
17 <select name="pubs" id="" class="form-control">
18 {% for pub in pub_list %}
19 {% if pub.id == book.publish.id %}
20 <option value="{{ pub.id }}" selected>{{ pub.name }}</option>
21 {% else %}
22 <option value="{{ pub.id }}">{{ pub.name }}</option>
23 {% endif %}
24 {% endfor %} 25 </select> 26 </div> 27 <div class="form-group"> 28 <label for="">作者</label> 29 <select name="authors" id="" class="form-control" multiple> 30 {% for author in author_list %}32 {% if author in book.author.all %} 33 <option value="{{ author.id }}" selected>{{ author.name }}</option> 34 {% else %} 35 <option value="{{ author.id }}">{{ author.name }}</option> 36 {% endif %} 38 {% endfor %} 39 </select> 40 </div> 41 <input type="submit" value="提交" class="btn btn-warning"> 42 </form>
注意:
- Django提交form表單。要加 {% csrf_token %}。不然會報403錯誤
- 還是先來看看這個繁瑣的form表單,每個input後面都有value。如果單單是新增書籍的話,vlaue可以為空。但是考慮到後面還有個編輯頁面。編輯的時候,input是有值的。所以我們也不能一步步往死裡寫,立馬轉彎,設計一條編輯書籍的url。
-
1 re_path('^book_edit/(?P<book_id>\d+)/$', views.book_edit, name='book_edit'), 2 # 匹配的url是這種的 :/book_edit/1/ 添加了一個有名分組,用來捕獲書籍id。走的是book_edit檢視
到這裡最好把之前要用到這條url的地方改一下。index.html有個編輯按鈕:
1 <a href="{% url 'book_edit' book.id %}"> 2 <button class="btn btn-success">編輯</button> 3 </a>
4 <!--用到了反向解析,因為index頁面每一行表記錄,都有一本書,書的id就是你要編輯的那本書的id-->
改完模板部分就是寫book_edit檢視了。
1 def book_edit(request, book_id):
2 book = Book.objects.filter(pk=book_id).first()
3 pub_lt = Publish.objects.all()
4 authors = Author.objects.all()
5 return render(request, 'book_edit.html', {"book": book, "pub_list": pub_lt, "author_list": authors})
6 # 和新增書籍不同的是,我們是編輯書籍,那本書原來的資料要保留渲染出來,所以我們的url後面要捕獲id。這裡資料庫過濾編輯的這本書物件。
7 # 渲染到之前的form表單頁面的value中,以後編輯書籍,就會自動2填充書修改之前的資料
- 還有一些你不懂的地方,我是把編輯和新增一同寫了,所以form表單中出版社和作者那裡還有for迴圈,還有if判斷。這麼多都是為編輯做鋪墊。
- 本來單單新增書籍,直接for迴圈後端傳來的pub_list就行。但是編輯就不一樣,編輯不僅value要填充,顯示的時候我們也要用select保留書籍原來所屬的出版社,所以我們for迴圈出版社,得到每一個出版社物件後,再if判斷我們此時編輯的書籍的出版社物件和for迴圈的出版社物件是否一致,如果一樣,就再option標籤加select表示,如果不一樣,就正常顯示,並不影響新增頁面。
- for迴圈作者也是一樣的道理。不同的是,一個書籍可能有多個作者,所以是判斷迴圈出來的作者物件在不在這本書籍的所有作者中,是,就select。因為多選所以select 還要加 multiple
-
其實這是一個比較繁瑣的介面,Django還有高階一點的玩法,我這裡不說,程式碼量減少的不是一般的多。。。什麼邏輯都不自己寫。我給你看個圖對比下。
就是這麼簡單粗暴。。。
寫到這裡,來看看效果吧。
發現一個很大的問題,沒有出版社和作者,渲染不出來,所以我們手動去資料庫加幾條資料。
再來看新增書籍頁面:
來試試編輯:
注意url。書籍原來的資訊就這樣顯現出來,歸功於那個form表單。