一,項目題目: 開發圖書管理頁面
該項目主要練習Django對多個數據庫進行增刪改查的操作。
二,項目需求:
基礎需求:75% 1. 列出圖書列表、出版社列表、作者列表 2. 點擊作者,會列出其出版的圖書列表 3. 點擊出版社,會列出旗下圖書列表 4. 可以創建、修改、刪除 圖書、作者、出版社 升級需求:10% 1. 點擊修改按鈕,彈出模塊框,模態框中展示該書的信息且信息可以修改, 2. 書名不可重復,不可修改 3. 修改圖書信息時,使用ajax請求發送信息
三,編碼規范需求:
編碼規范需求:15% 1. 代碼規范遵守pep8 (https://python.org/dev/peps/pep-0008/) 2. 函數有相應的注釋 3. 程序有文檔說明文件(README.md參考:https://github.com/csrftoken/vueDrfDemo) 4. 程序的說明文檔必須包含的內容:程序的開發環境(django版本)、程序的實現的功能、程序的啟動方式、登錄用戶信息、程序的運行效果 5. 程序設計的流程圖: (可以參考:https://www.processon.com/view/link/589eb841e4b0999184934329)
四,項目思路
首先做這個項目之前,推薦看一下我之前的博客:Django學習筆記(7):單表操作和多表操作,甚至有必要練習一遍。
其次,前期的基本操作,我在這里不再累贅,如果不會的話,可以參考我之前的博客:Django學習筆記(10)——Book單表的增刪改查頁面,當然,要是單表操作的增刪改查都不會,我覺得先練習一遍沒有壞處。
最后這里寫一下此項目的思路。此項目就是對多表操作的再鞏固。
4.1 創建模型
我們先來設定概念,字段和關系
作者模型 : 姓名 年齡 作者詳細模型 : 生日 手機號碼 家庭住址等等 出版商模型 : 出版商名稱 所在城市 email 書籍模型 : 書名 出版日期 用戶信息模型 :用戶名 密碼 (登錄注冊的用戶信息) (作者模型 和 作者詳細模型 一對一關系 one - to - one) (一本書可能會有多個作者, 一個作者也可以寫多本書 ) ( 作者 和 書籍 多對多的關系 many - to - many) (一本書只應該由一個出版商出版) ( 出版商和書籍 一對多關聯關系 one - to - many)
代碼如下:
from django.db import models
# Create your models here.
# 出版社類
class Publish(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
def __str__(self):
return self.name
# 書類
class Book(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=32)
publishDate = models.DateField()
price = models.DecimalField(max_digits=8, decimal_places=2)
# 書只能關聯一個出版社,外鍵通常建立在多的那一邊
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
# 多對多,作者和書是多對多的關系
books = models.ManyToManyField(to='Book', related_name='authors')
def __str__(self):
return self.title
# 作者類
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
# 作者和作者詳細信息 是一對一的關系
authordetail = models.OneToOneField(to='AuthorDetail', null=True,
on_delete=models.CASCADE)
# 作者詳細信息
class AuthorDetail(models.Model):
nid = models.AutoField(primary_key=True)
birthday = models.DateField()
telephone = models.BigIntegerField()
addr = models.CharField(max_length=64)
最后運行下面代碼,生成數據表:
python manage.py makemigrations python manage.py migrate
我們可以添加數據,我添加的數據如下:
insert into user1_authordetail values(1, '2019-11-12', '12345', 'boston'); insert into user1_authordetail values(2, '2014-11-12', '12312', 'houston'); insert into user1_authordetail values(3, '2013-11-12', '12432', 'ripcity'); insert into user1_author values(1, 'james', 34, 1); insert into user1_author values(2, 'durant', 31, 2); insert into user1_author values(3, 'curry', 30, 3); insert into user1_publish values(1, '機械出版社'); insert into user1_publish values(2, '草堂出版社'); insert into user1_publish values(3, '人民出版社');
4.2 APP下的URL具體內容整理
1,注冊
/register/
2,登錄
/login/
3,注銷
/logout/
4,圖書列表
/book_list/
/add_book/
/update_book/101/
/del_book/
5,出版社列表
/publisher_list/
/add_publisher/
/update_publisher/101/
# 通過出版社,修改該書,之后返回出版社頁面
/update_book/101/202/publisher/
/del_publisher/
# 通過出版社,查看該出版社的圖書列表
/book_list/101/publisher/
# 通過出版社,增加該出版社的某本書
/add_book/101/publisher/
# 通過出版社,刪除該出版社的某本書
/del_book/101/publisher/
6,作者列表
/author_list/
/add_author/
/update_author/101/
#通過作者,修改該書,之后返回作者頁面
/update_book/101/21/author
/del_author
# 通過作者,查看該作者的圖書列表
/book_list/101/author/
# 通過作者,增加該作者的某本書
/add_book/101/author/
# 通過作者,刪除該作者的某本書
/del_book/101/author/
這里我們以book單表的增刪改查頁面為例,然后增加連表操作,因為作者模型和作者詳細模型是一對一關系,而且書籍和作者是多對多的關系。我們這里以書籍,作者,作者詳細信息和出版社四張表的關系為例。
4.3 多表的查看操作
查看操作比較簡單,首先在view視圖函數中獲取所有book數據,將其顯示在頁面中,代碼如下:
book_list = Book.objects.all()
通過上面代碼獲取數據,拿到數據后,渲染給前端,前端通過for循環的方式,取出數據。目的就是通過Book這個數據表里面的字段拿到對應的數據。
前端代碼中,我們使用Bootstrap加入簡單的樣式,然后通過for循環拿出數據,將其顯示在前端頁面上。
注意1:這里Book表中,拿出的publishDate數據我們可以改成自己想要顯示的模型。
這里我們可以使用變量的過濾器(filter)。將數據顯示成 “xxxx-xx-xx”,代碼如下:
{{ book.publishDate|date:'Y-m-d' }}
注意2:這里的Book表中,因為一本書可能對應多個作者,所以我們在前端顯示的時候,想要給每個作者后面添加一個逗號(,),好看一下,但是最后一個不顯示逗號(,)。我們可以使用一個for循環,將其循環顯示:
{% for author in book.authors.all %}
{% if forloop.last %}
<span>{{ author.name }}</span>
{% else %}
<span>{{ author.name }}</span>,
{% endif %}
{% endfor %}
其他就沒什么難點,這里將books的HTML代碼顯示如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/dist/css/bootstrap.min.css">
</head>
<body>
<h3>查看書籍</h3>
<div class="container">
<div class="row">
<div class=" col-md-6 col-md-offset-3">
<a href="" class="form-group btn btn-primary">添加頁面</a>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>編號</th>
<th>書籍名稱</th>
<th>價格</th>
<th>出版日期</th>
<th>出版社</th>
<th>作者</th>
<th>修改操作</th>
<th>刪除操作</th>
</tr>
</thead>
<tbody>
{% for book in book_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ book.title }}</td>
<td>{{ book.price }}</td>
<td>{{ book.publishDate|date:'Y-m-d' }}</td>
<td>{{ book.publish.name }}</td>
<td>{% for author in book.authors.all %}
{% if forloop.last %}
<span>{{ author.name }}</span>
{% else %}
<span>{{ author.name }}</span>,
{% endif %}
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
4.4 多表的增加操作
添加操作的話,我們可以從前端寫起,我們獲取數據的各個變量,將其寫在form表單里面,然后傳到后台,如果是post的數據,我們可以將其獲取到,然后添加到數據庫中。
但是首先,我們需要獲取出版社的信息和作者的信息,因為出版社和Book是一對多的關系,作者和Book是多對多的關系,所以這里不是單純的添加,而是需要選擇。獲取Publish和Author信息的代碼如下:
publish_list = Publish.objects.all()
author_list = Author.objects.all()
然后,將信息展示在前端,從前端獲取的數據通過post傳到后台,進而寫入數據庫。
if request.method == 'POST':
title = request.POST.get('title')
price = request.POST.get('price')
pub_date = request.POST.get('pub_date')
publish_id = request.POST.get('publish_id')
# checkbox 多選的話,取值方式如下
authors_id_list = request.POST.getlist('authors_id_list')
# 添加到數據庫中,前面是數據庫的名字 =后面是上面變量的名字
book_obj = Book.objects.create(title=title, price=price, publishDate=pub_date,
publish_id=publish_id)
book_obj.authors.add(*authors_id_list)
return HttpResponse("OK")
注意1:由於一本書可以對應多個作者,所以我們獲取的作者數據可能是多個,那么我們不能直接get數據,這里使用 gstlist獲取多選數據。
authors_id_list = request.POST.getlist('authors_id_list')
注意2:由於作者和書是多對多的關系,所以我們添加數據,不止給Book表里添加,還將會添加Book和Authors表的關系,這里使用.add() 添加。代碼如下:
book_obj.authors.add(*authors_id_list)
最后這里展示一下添加數據的HTML代碼,(同樣這里使用Bootstrap渲染了頁面):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/dist/css/bootstrap.css">
</head>
<body>
<h3>添加書籍</h3>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form action="" method="post">
{% csrf_token %}
<div class="form-group">
<label for="">名稱</label>
<input type="text" name="title" class="form-control">
</div>
<div class="form-group">
<label for="">價格</label>
<input type="text" name="price" class="form-control">
</div>
<div class="form-group">
<label for="">出版日期</label>
<input type="date" name="pub_date" class="form-control">
</div>
<div class="form-group">
<label for="">出版社</label>
<select name="publish_id" id="" class="form-control">
{% for publish in publish_list %}
<option value="{{ publish.pk }}">{{ publish.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="">作者</label>
<select name="authors_id_list" multiple class="form-control">
{% for author in author_list %}
<option value="{{ author.pk }}">{{ author.name }}</option>
{% endfor %}
</select>
</div>
<input type="submit" class="btn btn-default">
</form>
</div>
</div>
</div>
</body>
</html>
4.5 多表的編輯操作和刪除操作
這里將編輯操作和刪除操作放在一起寫,肯定有其道理的。因為編輯操作和刪除操作,只需要在查看書籍的HTML上添加兩個按鈕,也就是編輯按鈕和刪除按鈕。
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
......
<th>修改操作</th>
<th>刪除操作</th>
</tr>
</thead>
<tbody>
{% for book in book_list %}
<tr>
......
<td>
<a href="{{ book.pk }}/change" class="btn btn-warning">編輯</a>
</td>
<td>
<a href="{{ book.pk }}/delete" class="btn btn-danger">刪除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
4.5.1 編輯功能的制作
首先,我們需要拿到需要編輯的ID,然后在數據庫中找到對應的ID字段,最后對內容進行修改。
edit_book_obj = Book.objects.filter(pk=edit_id).first()
publish_list = Publish.objects.all()
author_list = Author.objects.all()
這里再重復一次,因為Book和Publish是一對多的關系,Book和author是多對多的關系,所以同時需要將publish和author的數據取出來,同時進行update。
def change_books(request,edit_id):
edit_book_obj = Book.objects.filter(pk=edit_id).first()
publish_list = Publish.objects.all()
author_list = Author.objects.all()
if request.method == 'POST':
title = request.POST.get('title')
price = request.POST.get('price')
pub_date = request.POST.get('pub_date')
publish_id = request.POST.get('publish_id')
# checkbox 多選的話,取值方式如下
authors_id_list = request.POST.getlist('authors_id_list')
# 添加到數據庫中,前面是數據庫的名字 =后面是上面變量的名字
book_obj = Book.objects.filter(pk=edit_id).update(title=title, price=price, publishDate=pub_date,
publish_id=publish_id)
# 先把更新過的數據清空掉,然后再添加信息
# edit_book_obj.authors.clear()
# edit_book_obj.authors.add(*authors_id_list)
# set方法 可以取代上面的兩行代碼。
edit_book_obj.authors.set(authors_id_list)
return redirect('/user1/books/')
return render(request, 'user1/editbook.html', locals())
除了之前需要注意的問題之外,這里我們還需要注意兩點。
注意1:我們將數據update之后,我們需要展示的編輯之后的Book頁面,所以這里使用redirect,返回到book表中:
return redirect('/user1/books/')
注意2:我們添加author表的數據,所以我們不能拿到更新之后的信息,這里需要更新之前的信息,所以我們需要把更新過的數據清空掉,然后再添加數據。這里有兩種方法:
# 先把更新過的數據清空掉,然后再添加信息
# 方法一
edit_book_obj.authors.clear()
edit_book_obj.authors.add(*authors_id_list)
# 方法二
# set方法 可以取代上面的兩行代碼。
edit_book_obj.authors.set(authors_id_list)
最后展示完整的編輯視圖函數:
def change_books(request,edit_id):
edit_book_obj = Book.objects.filter(pk=edit_id).first()
publish_list = Publish.objects.all()
author_list = Author.objects.all()
if request.method == 'POST':
title = request.POST.get('title')
price = request.POST.get('price')
pub_date = request.POST.get('pub_date')
publish_id = request.POST.get('publish_id')
# checkbox 多選的話,取值方式如下
authors_id_list = request.POST.getlist('authors_id_list')
# 添加到數據庫中,前面是數據庫的名字 =后面是上面變量的名字
book_obj = Book.objects.filter(pk=edit_id).update(title=title, price=price,
publishDate=pub_date,
publish_id=publish_id)
# 先把更新過的數據清空掉,然后再添加信息
# edit_book_obj.authors.clear()
# edit_book_obj.authors.add(*authors_id_list)
# set方法 可以取代上面的兩行代碼。
edit_book_obj.authors.set(authors_id_list)
return redirect('/user1/books/')
return render(request, 'user1/editbook.html', locals())
4.5.2 刪除功能的制作
刪除就非常簡單了,我們只需要通過查找需要編譯的ID,然后在數據庫找到對應ID字段,刪除ID字段對應的數據即可。最后返回Book表就行。
這里展示刪除視圖的完整代碼:
def delete_books(request,delete_id):
Book.objects.filter(pk=delete_id).delete()
return redirect('/user1/books/')
五,注意事項
1,ORM表關系
一對一(author authordetail)
刪除author表時,應該刪除authordetail表,關聯的author就被刪除了!
一對多(book publisher)
刪除出版社下面的某本書,拿到書的id,刪除這本書
多對多(book author)
清楚綁定關系,不是刪除書
1.1 打印ORM轉換過程中SQL的代碼
如果不了解其關系,可以在控制台打印其SQL語句,也就是打印ORM轉換過程中的SQL,我們可以在Settings中配置一下:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
1.2 related_name的應用
在反向查詢的時候,如果定義了related_name,則使用 related_name替換表名,例如:
publish = ForeignKey(Blog, related_name='bookList')
練習:
# 練習: 查詢人民出版社出版過的所有書籍的名字與價格(一對多)
# 反向查詢 不再按表名:book,而是related_name:bookList
queryResult=Publish.objects
.filter(name="人民出版社")
.values_list("bookList__title","bookList__price")
2,引入Bootstrap文件
2.1 配置搜索目錄
在項目的根目錄下新建一個static目錄,然后打開項目的settings文件,在最下面添加配置,用於指定靜態文件的搜索目錄:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
2.2 下載Bootstrap文件
找到Bootstrap官網:點擊我
然后下載Bootstrap,將其解壓,然后放到static下面即可。
2.3 使用Bootstrap文件
注意:Bootstrap的所有JavaScript插件都依賴jQuery,所以必須將jQuery放在前面,不然bootstrap永遠引入失敗。
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依賴 jQuery,所以必須放在前邊) --> <script src="/static/JS/jquery-3.2.1.min.js"></script> <!-- 加載 Bootstrap 的所有 JavaScript 插件。你也可以根據需要只加載單個插件。 --> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
3,locals()函數的使用技巧
對於添加函數,我們發現了其return的時候,賦值操作如下:
return render(request, 'user1/addbook.html', {'publish_list': publish_list,
'author_list': author_list})
我們會發現,如果臨時變量和臨時模板有很多的時候,輸起來就非常麻煩,所以為了代碼看起來更加簡潔,我們可以使用Python的內建函數 locals(),它返回的字典對所有局部變量的名稱和值進行映射。因此上面的代碼可以重構如下:
return render(request, 'user1/addbook.html', locals())
在上面的代碼中,我們沒有手工指定其字典形式,而是傳入了locals()的值,他包括了函數執行的一切變量。
六,筆記
1,Django中timezone和Python中datatime的區別與聯系
- 進入django數據庫中的時候一定是timezone aware的時間,如果要生成時間,要通過replace timezone設置為本地失去。
- 數據庫中的時間都是UTC時間
1.1 Django中的timezone

1.2 Python中的datetime

2,def __str__(self): 是什么意思?
Python3.x中使用的是__str__ 函數 ,而Python2.x中使用的是__unicode__函數。
推薦定義Model的時候,寫一個__str__函數,它的作用是美化打印出來的結果,使我們更方便查看。
從最基本的說起,首先舉個例子:
class Test1:
def __init__(self, name, age):
self.name = name
self.age = age
class Test2:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "Name: " + self.name
res1 = Test1('james', 32)
print(res1)
res2 = Test2('durant', 30)
print(res2)
'''
<__main__.Test1 object at 0x00000000025700B8>
Name: durant
'''
我們可以看到:如果沒有__str__方法,打印出來的是<__main__.Test1 object at 0x00000000025700B8>格式,而有__str_-方法,打印出來是按照__str__定義的格式來打印,打印結果是Name: durant。
看看文檔

那么具體到Django中,在Models中定義這個__str__方法,最直接的感受就是你訪問admin所看到的的內容是否友好。
下面舉個例子:
class Question(models.Model):
question_text = models.CharField('question text', max_length=200)
pub_date = models.DateTimeField('date published')
class Meta:
verbose_name = 'question'
verbose_name_plural = verbose_name
ordering = ['-id']
def __str__(self):
return self.question_text
上面的models來自Django的官方教程(本人沒有實踐,只是拿過來做個筆記而已),在上面的models中,我定義了一個名為Question的models,此時訪問Django的后台admin,看到的內容是這樣的:

可以發現,Question看到的內容就是我們上面返回的self.question_text(如果返回的是其他形式,則結果是其他形式),那么如果此時將上述代碼注釋掉,也就是變成下面這樣:
class Question(models.Model):
question_text = models.CharField('question text', max_length=200)
pub_date = models.DateTimeField('date published')
class Meta:
verbose_name = 'question'
verbose_name_plural = verbose_name
ordering = ['-id']
再去看看后台admin里面查看Question,則變成這樣:

我們定義的問題,看到的內容全部變成了Question object,這樣的表達方式,對人來說,是相當的不友好,所以這就是定義一個__str__函數的必要性。
3,使用類視圖:減少重復代碼
當視圖里面代碼相似的時候,就顯得有點冗余。因為他們都具有類似的業務邏輯,實現類似的功能:通過從URL傳遞過來的參數去數據庫查詢數據,加載一個模板,利用剛才的數據渲染模板,返回這個模板,由於這個過程是如此的常見,Django很善解人意的幫助我們想辦法偷懶,於是提供了一種快捷方式,名為“類視圖”。
現在我們可以試試將原來代碼改為使用類視圖的方式,整個過程分三步走:
- 修改URLconf設置
- 刪除一些舊的無用的視圖
- 采用基於類視圖的新視圖
3.1 改良路由配置系統URLconf
URL配置(URLConf)就像是Django所支撐網站的目錄。它的本質是URL與要為該URL調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於客戶端發來的某個URL調用哪一段邏輯代碼對應執行。
比如下面代碼:
from django.conf.urls import url
from . import views
app_name = 'polls'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]
請注意:在上面的第2,3條目中將原來的question_id 改成了pk。若要從URL中捕獲一個值,只需要在它的周圍放置一對圓括號,不需要添加一個前導的反斜杠,因為每個URL都有。比如應該是^articles 而不是 ^/articles。
注意:每個正則表達式前面的 r 是可選的額但是建議加上,他告訴Python這個字符串是“原始的”——字符串中任何字符都不應該轉義。
七,結果展示
1,數據庫建好的表展示
1.1 插入數據之前,表格展示如下:
此次項目創建的所有的表格展示如下:

author表

author_books表

authordetail表

book表

publisher表

userinfo表

2,前端頁面展示如下:
Book表:

編輯頁面:

添加頁面:

八,代碼
8.1 簡易版本的增傷改查Book表
models.py
from django.db import models
# Create your models here.
# 出版社類
class Publish(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
def __str__(self):
return self.name
# 書類
class Book(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=32)
publishDate = models.DateField()
price = models.DecimalField(max_digits=8, decimal_places=2)
# 書只能關聯一個出版社,外鍵通常建立在多的那一邊
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
def __str__(self):
return self.title
# 作者類
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
# 作者和作者詳細信息 是一對一的關系
authordetail = models.OneToOneField(to='AuthorDetail', null=True, on_delete=models.CASCADE)
# 多對多,作者和書是多對多的關系
books = models.ManyToManyField(to='Book', related_name='authors')
# 作者詳細信息
class AuthorDetail(models.Model):
nid = models.AutoField(primary_key=True)
birthday = models.DateField()
telephone = models.BigIntegerField()
addr = models.CharField(max_length=64)
views.py
from django.shortcuts import render, HttpResponse,redirect
# Create your views here.
from user1.models import *
def add_book(request):
if request.method == 'POST':
title = request.POST.get('title')
price = request.POST.get('price')
pub_date = request.POST.get('pub_date')
publish_id = request.POST.get('publish_id')
# checkbox 多選的話,取值方式如下
authors_id_list = request.POST.getlist('authors_id_list')
# 添加到數據庫中,前面是數據庫的名字 =后面是上面變量的名字
book_obj = Book.objects.create(title=title, price=price, publishDate=pub_date,
publish_id=publish_id)
# print(authors_id_list) #['2', '3']
book_obj.authors.add(*authors_id_list)
return HttpResponse("OK")
publish_list = Publish.objects.all()
print(publish_list)
author_list = Author.objects.all()
return render(request, 'user1/addbook.html', {'publish_list': publish_list, 'author_list': author_list})
def books(request):
book_list = Book.objects.all()
return render(request, 'user1/books.html',{'book_list': book_list})
def change_books(request,edit_id):
edit_book_obj = Book.objects.filter(pk=edit_id).first()
publish_list = Publish.objects.all()
author_list = Author.objects.all()
if request.method == 'POST':
title = request.POST.get('title')
price = request.POST.get('price')
pub_date = request.POST.get('pub_date')
publish_id = request.POST.get('publish_id')
# checkbox 多選的話,取值方式如下
authors_id_list = request.POST.getlist('authors_id_list')
# 添加到數據庫中,前面是數據庫的名字 =后面是上面變量的名字
book_obj = Book.objects.filter(pk=edit_id).update(title=title, price=price, publishDate=pub_date,
publish_id=publish_id)
# 先把更新過的數據清空掉,然后再添加信息
# edit_book_obj.authors.clear()
# edit_book_obj.authors.add(*authors_id_list)
# set方法 可以取代上面的兩行代碼。
edit_book_obj.authors.set(authors_id_list)
return redirect('/user1/books/')
return render(request, 'user1/editbook.html', {'edit_book_obj': edit_book_obj,
'publish_list': publish_list,
'author_list': author_list})
def delete_books(request,delete_id):
Book.objects.filter(pk=delete_id).delete()
return redirect('/user1/books/')
urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('user1/', include('user1.urls')),
]
user1/urls.py
from django.contrib import admin
from django.urls import path, include
from user1 import views
urlpatterns = [
path('add/', views.add_book),
path('books/', views.books),
path('books/<int:edit_id>/change', views.change_books),
path('books/<int:delete_id>/delete', views.delete_books),
]
8.2 完整項目的代碼
請移步小編的GitHub:傳送門
