12.3 APP
12.31 創建APP
一個Django項目可以分為很多個APP,用來隔離不同功能模塊的代碼
用命令行創建一個APP:
python3 manage.py startapp app01
創建好APP,記得告訴Django,app的名字,在settings.py中添加:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01',#或者'app01.apps.App01Config', ]
12.32 Django中的ORM
Django項目使用MySQL數據庫
1.在Django項目的settings.py文件中,配置數據庫連接信息:告訴Django連接哪個數據庫
DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", "NAME": "db6", # 需要自己手動先創建數據庫 "USER": "root", "PASSWORD": "", "HOST": "127.0.0.1", "PORT": 3306 } }
2.Django默認使用的是 MySQLdb模塊 連接數據庫,但 MySQLdb在python3中不支持,所以:
在與Django項目同名的文件夾的__init__
.py文件中寫如下代碼,告訴Django使用pymysql模塊連接MySQL數據庫代替MySQLdb:
import pymysql pymysql.install_as_MySQLdb()
3.在app/models.py文件中定義類,一定要繼承models.Model
from django.db import models class User(models.Model): id = models.AutoField(primary_key=True) # 自增主鍵 name = models.CharField(max_length=16) # varchar(16) pwd = models.CharField(max_length=128) # varchar(128) # 出版社 class Publisher(models.Model): id = models.AutoField(primary_key=True) # 自增主鍵 name = models.CharField(max_length=16) # varchar(16) # 出版社名稱 #def __str__(self): #定義__str__是在打印表的對象時可以看到每一行的字段 # return (self.id,self.name) # 書籍 class Book(models.Model): id = models.AutoField(primary_key=True) # 自增的主鍵 title = models.CharField(max_length=32) # 書籍名稱 varchar(32) publisher = models.ForeignKey(to="Publisher") # 外鍵關聯Publisher這張表 # 作者 class Author(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) books = models.ManyToManyField(to="Book") # ORM創建多對多字段,會自動在數據庫中創建第三張表 id Author_id、Book_id
用命令行執行創建表的操作:
1. python3 manage.py makemigrations --> 將models.py的修改登記到小本本上
2. python3 manage.py migrate --> 將修改翻譯成SQL語句,去數據庫執行
4.在app/views.py文件中寫urls.py中 /publisher_list/ 的對應函數publisher_list;/add_publisher/的對應函數add_publisher
urls.py中的對應關系:
from django.conf.urls import url from django.contrib import admin from app01 import views # 對應關系 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), url(r'^publisher_list/', views.publisher_list), # 展示出版社列表 url(r'^add_publisher/', views.add_publisher), # 添加出版社 url(r'^delete_publisher/', views.delete_publisher), # 刪除出版社 url(r'^edit_publisher/', views.edit_publisher), # 編輯出版社 url(r'^book_list/', views.book_list), # 書籍列表 url(r'^add_book/', views.add_book), # 添加書籍 url(r'^delete_book/', views.delete_book # 刪除書籍 url(r'^edit_book/', views.edit_book), # 編輯書籍 url(r'^author_list/', views.author_list), # 作者列表 url(r'^add_author/', views.add_author), # 添加作者 url(r'^delete_author/', views.delete_author), # 刪除作者 url(r'^edit_author/', views.edit_author), # 編輯作者 url(r'^$', views.publisher_list) # 以上對應關系都找不到,就匹配出版社頁面 ]
app/views.py:
12.321 有關出版社的函數邏輯
from django.shortcuts import HttpResponse, render, redirect from app01 import models # 顯示出版社列表 def publisher_list(request): ret = models.Publisher.objects.all() # 從數據庫中取出所有的數據對象列表 #print(ret) return render(request, "publisher_list.html", {"publisher_list": ret}) #添加出版社函數 def add_publisher(request): # 根據請求方法的不同,要做不同的事情,add_publisher.html使用POST方法 if request.method == "POST":#request.method獲取的是請求的方法(GET、POST...必須是大寫) #request.POST(字典)獲取POST提交過來的全部數據 new_publisher_name = request.POST.get("publisher_name") models.Publisher.objects.create(name=new_publisher_name)#創建對象並封裝屬性(插入一行數據) #或者自己用類實例化一個對象:obj=models.Publisher(name=new_publisher_name) obj.save() #讓用戶跳轉到publisher_list.html,顯示新增數據后的publisher_list.html頁面 return redirect("/publisher_list/") return render(request, "add_publisher.html") # 刪除出版社函數 def delete_publisher(request): #print(request.method) #print(request.GET) delete_id = request.GET.get("id") #拿到用戶要刪除的出版社的id值 #print(delete_id) obj = models.Publisher.objects.get(id=delete_id)#根據id值得到對象 obj.delete() #將數據刪除 return redirect("/publisher_list/") #讓用戶重新訪問publisher_list.html更新頁面 # 編輯出版社的函數 def edit_publisher(request): #edit_id = request.GET.get("id")如果用戶提交使用URL拼接id,那么從URL里面取id參數request.GET.get("id") if request.method == "POST": #如果是post請求,表示用戶已經編輯好了,向服務端提交修改后的新數據 edit_id = request.POST.get("edit_id") # 拿到已經修改的出版社id new_name = request.POST.get("name") # 拿到修改之后的出版社的名字 edit_obj = models.Publisher.objects.get(id=edit_id)#通過id找到數據行對象 edit_obj.name = new_name edit_obj.save() #保存修改,提交數據庫 return redirect("/publisher_list/") # 修改成功,讓用戶跳轉到出版社列表頁面,更新頁面 #如果不是post請求,則返回edit_publisher.html頁面給用戶修改出版社 edit_id = request.GET.get("id") #先獲取編輯的出版社的ID值 obj = models.Publisher.objects.get(id=edit_id) #根據id值去數據庫找對應的行數據對象 return render(request, "edit_publisher.html", {"publisher": obj})#將數據想要編輯的出版社顯示出來,等待用戶編輯
templates/publisher_list.html:

<body> <table border="1"> <thead> <tr> <th>#</th> <th>出版社名稱</th> </tr> </thead> <tbody> {% for publisher in publisher_list %} <tr> <td>{{ publisher.id }}</td> #{{ forloop.counter }計數表格中的數據條數,從而刪除后更新id <td>{{ publisher.name }}</td> <td class="text-center"> <a class="btn btn-info btn-sm" href="/edit_publisher/?id={{ publisher.id }}"> <i class="fa fa-pencil fa-fw" aria-hidden="true"></i> 編輯 </a> <a class="btn btn-danger btn-sm" href="/delete_publisher/?id={{ publisher.id }}"> <i class="fa fa-trash-o fa-fw" aria-hidden="true"></i>刪除 </a> </td> </tr> {% endfor %} </tbody> </table> </body>
templates/add_publisher.html:

<body> <h1>添加新的出版社</h1> <form action="/add_publisher/" method="post"> <input type="text" name="publisher_name"> <input type="submit" value="提交"> </form> </body>
templates/edit_publisher.html:

#如果#action="/edit_publisher/?id={{ publisher.id }}"那么就從URL中用request.GET.get()取id參數 <form class="form-horizontal" action="/edit_publisher/" method="post"> <input type="text" name="edit_id" value="{{ publisher.id }}" class="hide">#將獲取id的input框隱藏 <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">出版社名稱</label> <div class="col-sm-9"> <input type="text" class="form-control" id="inputEmail3" name="name" placeholder="出版社名稱" value="{{ publisher.name }}">#提交出版社名稱 </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-default">提交</button> </div> </div> </form>
12.322 有關書籍的函數邏輯
from django.shortcuts import HttpResponse, render, redirect from app01 import models # 書籍列表函數 def book_list(request): ret = models.Book.objects.all() #去數據庫查詢所有的書籍對象 return render(request, "book_list.html", {"book_list": ret})#將數據填充到頁面上,發送給客戶端 # 添加書籍函數 def add_book(request): if request.method == "POST": #如果是POST請求表示用戶新添加了一本書籍和關聯的出版社 book_name = request.POST.get("book_name") # 添加新書籍的名稱 publisher_id = request.POST.get("publisher_id") # 添加新書籍關聯的出版社id值 models.Book.objects.create(title=book_name, publisher_id=publisher_id) #publisher_obj = models.Publisher.objects.get(id=publisher_id)#根據id值先找到關聯的出版社對象 #models.Book.objects.create(title=book_name, publisher=publisher_obj) return redirect("/book_list/") # 創建成功,讓用戶跳轉到書籍列表頁面,刷新數據 # 取到所有的出版社數據,在頁面上渲染成select標簽,供用戶選擇 ret = models.Publisher.objects.all() return render(request, "add_book.html", {"publisher_list": ret}) # 刪除書籍的函數 def delete_book(request): delete_book_id = request.GET.get("id") # 從URL里面取到要刪除的書籍的ID models.Book.objects.get(id=delete_book_id).delete()# 去數據庫中刪除 return redirect("/book_list/") # 刪除成功,跳轉到書籍列表頁面,刷新數據 # 編輯書籍的函數 def edit_book(request): if request.method == "POST": # 如果是POST請求 表名是用戶修改好了數據,向后端提交了 new_book_title = request.POST.get("book_title") # 取用戶提交過來的數據 new_publisher_id = request.POST.get("publisher_id") book_id = request.GET.get("id") #獲取URL中的當前編輯圖書的id book_obj = models.Book.objects.get(id=book_id)# 根據id取出要編輯的書籍對象 book_obj.title = new_book_title book_obj.publisher_id = new_publisher_id book_obj.save() # 將修改保存到數據庫 return redirect("/book_list/") # 修改完之后讓用戶跳轉回書籍列表頁面 # 返回一個讓用戶編輯數據的頁面 edit_book_id = request.GET.get("id") # 取編輯的書籍的id值 edit_book_obj = models.Book.objects.get(id=edit_book_id) # 取到要編輯的書籍對象 publisher_list = models.Publisher.objects.all() # 去數據庫查詢目前所有的出版社數據 return render(request,"edit_book.html",{"book": edit_book_obj,"publisher_list":publisher_list})
templates/book_list.html:

<table class="table table-striped table-bordered"> <thead> <tr> <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.publisher.name}}</td># book.publisher拿到的是外鍵(id)關聯的出版社的行數據對象 <td class="text-center"> <a class="btn btn-info btn-sm" href="/edit_book/?id={{ book.id }}"> <i class="fa fa-pencil fa-fw" aria-hidden="true"></i> 編輯 </a> <a class="btn btn-danger btn-sm" href="/delete_book/?id={{ book.id }}"> <i class="fa fa-trash-o fa-fw" aria-hidden="true"></i> 刪除 </a> </td> </tr> {% endfor %} </tbody> </table>
templates/add_book.html:

<form class="form-horizontal" action="/add_book/" method="post"> <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">書籍名稱</label> <div class="col-sm-9"><input type="text" class="form-control" id="inputEmail3" name="book_name" placeholder="書籍名稱"> </div> </div> <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">出版社名稱</label> <div class="col-sm-9"> <select class="form-control" name="publisher_id"> {% for publisher in publisher_list %} <option value="{{ publisher.id }}"> {{ publisher.name }} </option> {% endfor %} </select> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"><button type="submit" class="btn btn-default">提交</button> </div> </div> </form>
templates/edit_book.html:

#action=""此處使用默認URL,即繼承之前的/edit_book/?id={{ book.id }} #或者#action="/edit_publisher/?id={{ publisher.id }}"那么就從URL中用request.GET.get()取id參數 <form class="form-horizontal" action="" method="post"> #隱藏要編輯的書,發送id到后端,為了在后端找到要修改的圖書,方便修改 #<input type="text" value="{{ book.id }}" name="book_id" class="hide"> #預先在輸入框和下拉框顯示要修改的圖書名和出版社名 <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">書籍名稱</label> <div class="col-sm-9"> <input type="text" class="form-control" id="inputEmail3" name="book_title" value="{{ book.title }}" placeholder="書籍名稱"> </div> </div> <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">出版社名稱</label> <div class="col-sm-9"> <select class="form-control" name="publisher_id"> # 如果當前循環到的出版社和書關聯的出版社相等,則添加selected,表示預先選中的 {% for publisher in publisher_list %} {% if publisher == book.publisher %} <option value="{{ publisher.id }}" selected>{{ publisher.name }}</option> {% else %} <option value="{{ publisher.id }}">{{ publisher.name }}</option> {% endif %} {% endfor %} </select> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-default">提交</button> </div> </div> </form>
12.323 有關作者的函數邏輯
# 作者列表函數 def author_list(request): authors = models.Author.objects.all() # 從數據庫中查詢所有的作者數據,在頁面上展示出來 # author_obj = models.Author.objects.get(id=1) # print(author_obj.books.all()) 表示id=1的作者寫的所有書的對象 return render(request, "author_list.html", {"author_list": authors}) # 添加作者函數 def add_author(request): if request.method == "POST": new_author_name = request.POST.get("author_name") # 拿到新的作者姓名 models.Author.objects.create(name=new_author_name)# 去數據庫中創建一個新的作者記錄 return redirect("/author_list/") # 創建好作者之后,讓用戶跳轉到作者列表頁面 # 返回一個頁面,讓用戶填寫新的作者信息 return render(request, "add_author.html") # 刪除作者函數 def delete_author(request): delete_author_id = request.GET.get("id") # 從URL里面取到要刪除的作者的ID models.Author.objects.get(id=delete_author_id).delete()# 去數據庫中找到該作者並刪除 return redirect("/author_list/") # 刪除成功后 跳轉回作者列表頁面 # 編輯作者函數 def edit_author(request): if request.method == "POST": # 如果發送的是POST請求,應該拿到用戶提交的數據 edit_author_id = request.POST.get("author_id") # 編輯的作者id # 取新名字和新的書籍id new_author_name = request.POST.get("author_name") new_book_ids = request.POST.getlist("book_ids") # 如果提交過來的數據是多個值(多選的select/多選的checkbox)則使用getlist取列表 # print(request.POST) # print(edit_author_id, new_author_name, new_book_ids) # 去編輯作者以及對應的書籍 edit_author_obj = models.Author.objects.get(id=edit_author_id)# 拿到編輯的作者對象 edit_author_obj.name = new_author_name # 修改作者姓名 edit_author_obj.save() # 修改作者寫的書籍 edit_author_obj.books.set(new_book_ids) #通過新書id更換作者對應的書籍,並提交數據庫 return redirect("/author_list/") # 修改完成之后,跳轉到作者列表頁面 # 返回一個頁面,讓用戶編輯 edit_author_id = request.GET.get("id") # 從URL里面取到要編輯作者的id參數 edit_author_obj = models.Author.objects.get(id=edit_author_id)# 取到要編輯的作者對象 book_list = models.Book.objects.all() # 獲取所有的書籍對象信息 return render(request,"edit_author.html",{"author": edit_author_obj,
templates/author_list.html:

<div class="col-md-3 col-sm-6 pull-right add-btn"> <button data-target="#myModal" data-toggle="modal" class="btn btn-success pull-right">新增 </button> <a href="/add_author/" class="btn btn-info pull-right">新頁面添加 </a> </div> <table class="table table-striped table-bordered"> <thead> <tr> <th>序號</th> <th>作者姓名</th> <th>著作</th> <th>操作</th> </tr> </thead> <tbody> {% for author in author_list %}#{"author_list": authors} <tr> <td>{{ forloop.counter }}</td> <td>{{ author.name }}</td> <td> #在這一列展示這個作者關聯的所有的書籍 {% for book in author.books.all %}#書籍對象的列表 {% if forloop.last %} 《{{ book.title }}》 {% else %} 《{{ book.title }}》, {% endif %} {% empty %} 暫無著作 {% endfor %} </td> <td class="text-center"> <a class="btn btn-info btn-sm" href="/edit_author/?id={{ author.id }}"> <i class="fa fa-pencil fa-fw" aria-hidden="true"></i>編輯 </a> <a class="btn btn-danger btn-sm" href="/delete_author/?id={{ author.id }}"> <i class="fa fa-trash-o fa-fw" aria-hidden="true"></i>刪除 </a> </td> </tr> {% endfor %} </tbody> </table>
templates/add_author.html:

<form class="form-horizontal" action="/add_author/" method="post"> <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">作者姓名</label> <div class="col-sm-9"> <input type="text" class="form-control" id="inputEmail3" name="author_name" placeholder="作者姓名"> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-default">提交</button> </div> </div> </form>
templates/edit_author.html:

<form class="form-horizontal" action="" method="post">#action=""默認轉到當前URL <input type="text" value="{{ author.id }}" name="author_id" class="hide"> <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">作者姓名</label> <div class="col-sm-9"> <input type="text" class="form-control" id="inputEmail3" name="author_name" value="{{ author.name }}" placeholder="作者姓名"> </div> </div> <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">著作</label> <div class="col-sm-9"> <select class="form-control" name="book_ids" multiple> {% for book in book_list %} #book_list 所有的書籍對象 #author:要編輯的作者,author.books.all:要編輯的作者的所有書籍對象 {% if book in author.books.all %} # 如果當前這本書在作者寫的書里面 <option value="{{ book.id }}" selected>{{ book.title }}</option> {% else %} <option value="{{ book.id }}">{{ book.title }}</option> {% endif %} {% endfor %} </select> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-default">提交</button> </div> </div> </form>