做者的管理 html
出版社 書籍 做者數據庫
一個出版社出版多個書籍 1對多django
書籍和做者的關係:一個做者寫多本書,一本書能夠是多個做者寫。多對多app
1)建立一張表,表中多對多的數據關係。使用 多對多字段的方法ide
2)建立的這個類,會建立兩個表,app_加類名(開頭變小寫),app_這個類名_另外一張表類名函數
3)這個類建立的表中沒有多對多的字段,多對多的關係是以這張表表名加_id和另外一張表表名加_id兩個字段合成的新的表,id主鍵自動生成oop
4)通常多對多字段關聯的是有外鍵的那張表。url
url(r'^author_list/', views.author_list),
# 展現做者
for author in all_authors: print(author) print(author.pk) print(author.name) print(author.books,type(author.books)) # 關係管理對象 print(author.books.all(),type(author.books.all())) print('*'*30)
def author_list(request): # 查詢全部的做者 all_authors = models.Author.objects.all() return render(request,'author_list.html',{'all_authors':all_authors})
點擊這裏可清空打印內容:spa
打印查看各個變量的含義設計
<class 'django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager'> 關係管理對象
經過關係管理對象.all()拿到全部關聯的對象
由上可知:從做者表author.books.all()[0].title 得到了book表的書名,那麼由author.books.all()[0].pub就能得到對應的一條出版社表的記錄。從這張多對多關係的表中,獲取到對應多對多關係另外一張表的多條記錄,又由此能得到另外一張表的具備外鍵的對應的外鍵表記錄,三表聯繫在一塊兒了。
Book和Author多對多的關係。books是Author中你想要的對象跟Book關聯的全部對象。books的做用是在Author和Book中建立一箇中間的關係對象,放在第三張表中,再根據這個中間的關係來獲取Book中關聯的對象
外鍵和多對多關係區別:
外鍵是根據book.pub拿到的就是關聯的外鍵對象(每行數據);而多對可能是Auther.books直接拿到的是一個關係管理對象,關係管理對象.all()才能拿到全部關聯對象(每行數據)。
一個錯誤:一個函數重定向到本身這個函數會出現遞歸現象,達到遞歸上限,報錯重定向次數過多,所以當這個函數想要從新返回到自身頁面的時候用render,轉到其它頁面用render或者重定向
{% for author in all_authors %} <tr> <td>{{ forloop.counter }}</td> <td>{{ author.pk }}</td> <td>{{ author.name }}</td> <td> {% for book in author.books.all %} {% if forloop.last %} 《{{ book.title }}》 {% else %} 《{{ book.title }}》、 {% endif %} {% endfor %} </td> </tr> {% endfor %}
將對象列表循環出來再取須要的字段,並添加書名號。
將循環出來的每一個內容用頓號隔開。
若是隻是在後面加個逗號,那麼最後那個都會顯示逗號:
for循環中批量操做數據,經過添加判斷實現知足條件的輸出不一樣內容,
# 新增出版社 def add_publisher(request): error = '' # 對請求方式進行判斷 if request.method == 'POST': # 處理POST請求 # 獲取到出版社的名稱 publisher_name = request.POST.get('publisher_name') # 判斷出版社名稱是否有重複的 if models.Publisher.objects.filter(name=publisher_name): error = '出版社名稱已存在' # 判斷輸入的值是否爲空 if not publisher_name: error = '不能輸入爲空' if not error: # 使用ORM將數據插入到數據庫中 obj = models.Publisher.objects.create(name=publisher_name) # 跳轉到展現出版社的頁面 return redirect('/publisher_list/') # 返回一個包含form表單的頁面 return render(request, 'add_publisher.html', {'error': error})
author_obj = models.Author.objects.create(name=author_name) # 只插入book表中的內容 author_obj.books.set(books) # 設置做者和書籍多對多的關係
一個功能,一個url地址,一個函數,外加一個模板。每一個功能都是這樣
添加做者,選擇做者寫的多個書籍,提交。實現多選功能:
添加做者:將提交的做者名字和做品獲取到並寫入數據庫,而後重定向到做者展現頁面
以下:在頁面選中多個提交,可是get獲取book的值只獲取到一個,應該是選擇的book列表纔是咱們想要的,可是get只是獲取到了最後一個數值
正確使用時getlist方法,獲取select中多選的值
getlist獲取到的類型是列表。多選中選中多個選項獲取的值:
存入數據庫:
1)先用input輸入的做者名字建立做者表對象
2)再獲取出來select選中多個關聯選項
3)新建的做者對象.books得到關係管理對象,關係管理對象.set(要關聯的多個外表的id列表)。由此,這個做者表對象set設置了和外表的多條記錄的關係映射,並在第三張表中體現出來
【1】插入數據【2】設置它對多的關係
以下演示:
結果以下:表之接.東西,報錯對象沒有這個屬性,這裏是缺乏objects了,直接表.create會把它當作表的字段看待
正確結果:,注意create不要將給多對多的表明關係管理對象的設置值
而後再設置重定向到book_list頁面
刪除操做邏輯以下:
拿到要刪除的數據id,而後查表找到對應數據進行刪除再返回到展現頁面
url設置,寫函數,做者展現首頁添加刪除按鈕:
刪除成功;
books = request.POST.getlist('books') # 修改對象的數據 author_obj.name = name author_obj.save() # 多對多的關係 author_obj.books.set(books) # 每次從新設置
編輯和添加的html差很少,直接複製過來修改一下:
有多對多關係的表數據編輯:
1)url
2)函數
3)html
(1)做者展現頁點擊編輯a標籤get請求並帶有編輯的對象pk跳轉到編輯頁
(2)編輯頁不是多對多關係的字段能夠用輸入框
(3)是多對多關係的須要使用多選框,多選框中是另外一個表中全部做品,被選中的即已是做者的做品 是與做者pk條件相等的做者表中關係管理對象的全部對象
邏輯關係以下:
# 編輯做者 def edit_author(request): # 查詢編輯的做者對象 pk = request.GET.get('pk') author_obj = models.Author.objects.get(pk=pk) if request.method == 'POST': # 獲取提交的數據 name = request.POST.get('author_name') books = request.POST.getlist('books') #注意是getlist,否則只能獲取到一個數字 # 修改對象的數據 author_obj.name = name author_obj.save() # 多對多的關係 author_obj.books.set(books) # 每次從新設置 #不論是新增仍是修改都使用set就好了 # 重定向 return redirect('/author_list/') # 查詢全部的書籍 all_books = models.Book.objects.all() #請求方式判斷在前,由於POST中用不到這個 return render(request, 'edit_author.html', {'author_obj': author_obj, 'all_books': all_books})
每次編輯都是從新設置,也就是set以前會把和這個對象在關聯表中關聯的刪掉並從新建立
class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book') # 不在Author表中生產字段,生產第三張表
class AuthorBook(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCADE) book = models.ForeignKey(Book, on_delete=models.CASCADE) date = models.DateField()
註銷不用books
class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book',through='AuthorBook') # 不在Author表中生產字段,生產第三張表 class AuthorBook(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCA DE) book = models.ForeignKey(Book, on_delete=models.CASCADE) date = models.DateField()
1)第三種方式可使用 ManyToManyField 方法,經過第一個字符串參數指定和哪一個表關聯;經過 through='自建第三張表'和自建第三張表聯繫起來,這樣它自己不會建立第三張關聯表了,而是以你寫的第三張表的來做爲它和它關聯表之間的多對多關聯關係。
2)這樣的好處是我能夠在django創建的關係表上添加字段(好比創建第三張關聯表,圖書id和做者id一一對應,可是我想要做者編寫圖書的時間,那麼最好的地方就是放到這張表,而自建第三張表的方式才能給表添加字段;可是自建的表查詢語句還要本身寫,)
3)自建第三張表既能增長數據表字段,也能經過books.all()獲取數據,可是不能使用set等某些方法,要想查數據仍是要本身寫語句
4)自建第三張表是本身設置另外兩張表的外鍵字段