[TOC]css
發送HTTP請求html
經過TCP套接字,客戶端Web服務器發送一個文本的請求報文,一個請求報文由請求行、請求頭部、空行、和 請求數據四部分組成
服務器接受請求並返回HTTP響應前端
Web服務器解析請求,定位請求資源。服務器將資源副本寫到TCP套接字,由客戶端讀取。一個響應由狀態行、響應頭部、空行和響應數據四部分組成
在瀏覽器地址欄鍵入URL,按下回車以後經歷的過程node
1. 瀏覽器向DNS服務器請求解析該URL中的域名所對應的IP地址。 2. 解析出IP地址後,根據該IP地址和默認端口80,和服務器創建TCP鏈接。 3. 瀏覽器發出讀取文件(URL中域名後面部分對應的文件)的HTTP請求,該請求報文做爲TCP三次握手的第三次報文的數據發送給服務器 4. 服務器對瀏覽器做出響應,並把對應的html文本發送給瀏覽器 5. 釋放TCP鏈接 6. 瀏覽器渲染HTML並顯示內容
HTTP請求方法python
1. GET : 向指定的資源發出"顯示"請求。使用GET方法應該只用在讀取數據上,而不該被用於產生"反作用"的操做中,例如在Web Application中,其中一個緣由是GET可能會被網絡蜘蛛等隨意訪問. 2. HEAD : 與GET方法同樣,都是向服務器發出指定資源的請求。只不過服務器將不傳回資源的本文部分。它的好處在於,使用這個方法能夠在沒必要傳輸所有內容的狀況下,就能夠獲取其中「關於該資源的信息」(元信息或稱元數據)。 3. POST : 向指定資源提交數據,請求服務器進行處理(例如提交表單或者上傳文件)。數據被包含在請求本文中。這個請求可能會建立新的資源或修改現有資源,或兩者皆有。 4. PUT : 向指定資源位置上傳其最新內容。 5. DELETE : 請求服務器刪除Request-URI所標識的資源。 6. TRACE : 回顯服務器收到的請求,主要用於測試或診斷。 7. OPTIONS : 這個方法可以使服務器傳回該資源所支持的全部HTTP請求方法。用'*'來代替資源名稱,向Web服務器發送OPTIONS請求,能夠測試服務器功能是否正常運做。 8. CONNECT : HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。一般用於SSL加密服務器的連接(經由非加密的HTTP代理服務器)
HTTP狀態碼mysql
1xx消息——請求已被服務器接收,繼續處理 2xx成功——請求已成功被服務器接收、理解、並接受 : 200 ok - 請求成功 3xx重定向——須要後續操做才能完成這一請求 4xx請求錯誤——請求含有詞法錯誤或者沒法被執行 : 403 Forbidden - 服務器已經理解請求,可是拒絕執行它 404 Not Found - 請求失敗,請求所但願獲得的資源未被在服務器上發現。 5xx服務器錯誤——服務器在處理某個正確請求時發生錯誤
URLweb
1. 傳送協議。 2. 層級URL標記符號(爲[//],固定不變) 3. 訪問資源須要的憑證信息(可省略) 4. 服務器。(一般爲域名,有時爲IP地址) 5. 端口號。(以數字方式表示,若爲HTTP的默認值「:80」可省略) 6. 路徑。(以「/」字符區別路徑中的每個目錄名稱) 7. 查詢。(GET模式的窗體參數,以「?」字符爲起點,每一個參數以「&」隔開,再以「=」分開參數名稱與數據,一般以UTF8的 URL編碼,避開字符衝突的問題) 8. 片斷。以「#」字符爲起點
HTTP請求格式sql
請求方法 | 空格 | URL | 空格 | 協議版本 | 回車符 | 換行符 --→ 請求行 頭部字段名 | : | 值 | 回車符 | 換行符 } ... } --→ 請求頭部 頭部字段名 | : | 值 | 回車符 | 換行符 } !@#$%^&* ... --→ 請求數據
HTTP相應格式數據庫
協議版本 | 空格 | 狀態碼 | 空格 | 狀態碼描述 | 回車符 | 換行符 --→ 狀態行 頭部字段名 | : | 值 | 回車符 | 換行符 } ... } --→ 響應頭部 頭部字段名 | : | 值 | 回車符 | 換行符 } 請求方法 | 空格 | URL | 空格 | 協議版本 | 回車符 | 換行符 --→ 響應正文
mport socket # 建立一個socket對象 sk = socket.socket() # 綁定ip和端口 sk.bind(('127.0.0.1', 8848)) # 監聽 sk.listen() def index(url): ret = '歡迎進入紅浪漫! - {}'.format(url) return ret.encode('utf-8') def home(url): ret = '歡迎回家! - {}'.format(url) return ret.encode('utf-8') def help_me(url): ret = '再等30年,你又是條好漢! - {}'.format(url) return ret.encode('utf-8') list1 = [ ('/index', index), ('/home', home), ('/help_me', help_me), ] # 等待鏈接 while True: conn, addr = sk.accept() data = conn.recv(1024) url = data.decode('utf-8').split()[1] # 獲取用戶輸入的路徑 # for i in list1: # if url == i[0]: # ret = i[1](url) # break # else: # ret = '被查辦了!'.encode('utf-8') func = None for i in list1: if url == i[0]: func = i[1] break if func: ret = func(url) else: ret = '被查辦了!'.encode('utf-8') conn.send(b'HTTP/1.1 200 OK\r\ncontent-type: text/html; charset=utf-8\r\n\r\n') conn.send(ret) conn.close()
命令行下載安裝django
pip3 install django - 下載安裝的是最新版本 pip3 install django==1.11.23 -i https://pypi.tuna.tsinghua.edu.cn/simple - 選擇版本,選擇安裝源
建立項目
1. 首先進入要建立項目的文件夾 2. SHIFT + 鼠標右鍵 打開命令行 3. 執行命令 : django-admin startproject 項目名
啓動項目
python manage.py runserver # 默認127.0.0.1 : 80000 python manage.py runserver 80 # 修改 80端口 python manage.py runserver 0.0.0.0:80 # 修改地址和端口
pycharm
建立項目
1. New Project 2. Django - 選擇項目目錄 - 選python版本 - Create
啓動項目
選中項目目錄 - run(圖標)
pycharm建立項目的一些說明
1. settings.py會在項目根目錄下自動建立一個名字爲 templates 用於放HTML等文件的文件夾 : 'DIRS': [os.path.join(BASE_DIR, 'templates')] 2. 導入模塊 ( urls.py ): from django.shortcuts import HttpResponse,render def index(request): return HttpResponse('歡迎進入紅浪漫!') # 返回字符串 def home(request): return render(request,'home.html') # 返回html頁面 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home/', home), url(r'^index/', index), ] 3. 修改ip和端口 : Run → Edit Configurations
**項目中settings.py
文件下 😗*
STATIC_URL = '/static/' STATICFILES_DIRS = [ #按照列表的順序進行查找 os.path.join(BASE_DIR,'static'), os.path.join(BASE_DIR,'xxx') ] os.path.join(BASEDIR, 'static', 'css')是靜態文件存放的實際路徑,STATIC_URL='/static/'中的/statis/是這個路徑的別名。二者是一個映射關係,若是要使用該靜態文件,那麼靜態文件的URL中的"實際路徑部分"就要使用別名來代替
settings.py
配置好後, 須要在項目下新建文件static
, 這個static
是存放 CSS, JavaScript, Images
等靜態文件的一個根目錄form表單
form表單中 action 填寫提交表單的ip地址和端口 method 是提交請求方式 默認GET請求,html中要小寫 <form class="form-signin" action = "" method="post">
<input class="form-control" id="inputEmail" autofocus="" required="" type="email" placeholder="Email address" > required="" 是表單的必填項,刪除後,就能夠了
<input class="form-control" id="inputEmail" autofocus="" required="" type="email" name="username" placeholder="Email address"> <input class="form-control" id="inputPassword" required="" type="password" name="password" placeholder="Password"> 設置name的鍵值對
關掉pycharm的校驗請求功能 - csrf 中間件
在settings.py中 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
禁用前端校驗
form表單中添加 novalidate <form class="form-signin" action = "" method="post" novalidate>
urls.py
中校驗請求(用戶名密碼校驗)
from django.shortcuts import HttpResponse, render, redirect def index(request): # 業務邏輯 return HttpResponse('歡迎進入紅浪漫!') def home(request): return render(request, 'home.html') def login(request): if request.method == 'GET': # 返回登陸頁面 return render(request, 'login.html') elif request.method == 'POST': # 獲取提交的數據 request.POST username = request.POST.get('username') password = request.POST.get('password') # 對用戶名和密碼進行校驗 if username == 'alex' and password == 'alexdsb': # 校驗成功 跳轉到首頁(重定向) # return HttpResponse('歡迎進入紅浪漫!') return redirect('/index/') else: # 校驗失敗 從新登錄 return render(request, 'login.html')
咱們在項目中的urls中配置路由,在templates 裏寫HTML文件,若是項目很大,路由不少,HTML文件不少,那麼就須要在項目的內部與與項目同名的同級建立APP應用,在APP應用裏能夠寫本身的urls和views 這樣主路由中的路由能夠映射到APP中的子路由,這個時候就像一個樹的根部到樹葉擴散。
建立app
CMD建立 : 進入項目文件夾下,按住shift右鍵進入命令行 : python manage.py startapp app名稱 pycharm中 : 在Teminal命令行中鍵入命令 : python manage.py startapp app名稱 利用pycharm中的tools工具建立 : 1. 調出窗口 : tools → Run manage.py Task ... 2. 鍵入命令 : startapp app名
註冊app
在settings中 : INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', # 第一種方式 'app01.apps.App01Config', # 第二種方式 推薦寫法 ]
app下的目錄解釋
admin.py django admin apps.py app的信息 models.py 模型 model 跟數據庫有關 views.py 寫函數(以前在urlspy中寫的函數寫在這裏
**將urls.py
中的函數轉移到建立的app
下的views.py
😗*
views.py下的全面內容
from django.shortcuts import render,redirect,HttpResponse def login(requset): if requset.method == 'GET': # 返回登陸頁面 return render(requset,'login.html') elif requset.method == 'POST': # 獲取提交的數據 (用戶名和密碼) username = requset.POST.get('username') password = requset.POST.get('password') # 對用戶名和密碼進行校驗 if username == 'python' and password == '123': # 校驗成功,跳轉到設置頁面(重定向) return redirect('http://donyz.s567.tw/') else: # 校驗失敗,從新登陸 return render(requset,'login.html')
將views.py
中的函數導入到urls.py
中
urls.py文件下 : from app01 import views # 導入 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), # 引用 ]
對象關係映射(Object Relational Mapping,簡稱ORM)是經過使用描述對象和數據庫之間映射的元數據,將面嚮對象語言程序中的對象自動持久化到關係數據庫中。本質上就是將數據從一種形式轉換到另一種形式。 對應關係 類 -- 表 對象 -- 數據行 屬性 -- 字段 * orm能夠操做表,操做數據行
**1. CMD命令行建立數據庫 : ** create database Day54
2. settings.py
的配置
# settings.py下 : DATABASES = { 'default': { 'ENGINE' : 'django.db.backends.mysql', # 數據庫類型 'NAME' : 'Day54', # 數據庫名 'HOST' : '127.0.0.1', # IP地址 'PORT' : 3306, # 數據庫的端口 'USER' : 'root' # 數據庫用戶名 'PASSWORD' : '2108' # 密碼 } }
3. 使用pymysql
模塊鏈接mysql數據庫 (__init__.py
)
在項目同名的文件夾下的__init__.py中 : 下面這兩行代碼也能夠不在__init__.py中,只要能運行就能夠 # 導入pymysql模塊 import pymysql # 用pymysql模塊替換掉mysqldb模塊 由於默認使用的是mysldb模塊,此模塊僅支持python2, pymysql.install_as_MySQLdb()
**4. 寫pymysql
模塊與數據庫的對應關係 **
在app下的models.py中寫表結構 : from django.db import models class User(models.Model): # 建立類,繼承Model類的功能 username = models.CharField(max_length=32) # 數據庫中表的字段 類型爲varchar(32) password = models.CharField(max_length=32) # 數據庫中表的字段 類型爲varchar(32)
5. 執行創數據庫遷移的命令
pycharm的Teminal命令窗口下 : python manage.py makemigrations # 記錄下models.py的變動記錄並更新到 migrations 文件夾下的 001_inittal.py文件中 python manage.py migrate # 把變動記錄同步到數據庫中 這樣上面的數據庫表結構就寫入數據庫了
6. 利用pycharm
查看數據庫
**最新版的pycharm在鏈接中遇到因爲時區貳沒法鏈接數據庫的問題的解決辦法 😗*
在鏈接數據庫窗口: 在數據庫路徑後加 ?serverTimezone=GMT 便可
**注意 😗*
在pycharm中修改數據庫後須要提交,修改纔會生效
7. 利用數據庫進行用戶名密碼校驗
from django.shortcuts import render,redirect from app01 import models # 導入models.py中的User等類 def login(requset): if requset.method == 'GET': # 返回登陸頁面 return render(requset,'login.html') elif requset.method == 'POST': # 獲取提交的數據 (用戶名和密碼) user = requset.POST.get('username') pwd = requset.POST.get('password') # 對用戶名和密碼進行校驗 ret = models.User.objects.filter(username=user,password=pwd) # filter - 過濾篩選 查不到爲空(False)對象列表 # ret = models.User.objects.get(username=user,password=pwd) # get - 找不到會報錯,找到多個也會報錯 if ret: # 校驗成功,跳轉到設置頁面(重定向) return redirect('http://donyz.s567.tw/') else: # 校驗失敗,從新登陸 return render(requset,'login.html')
出版社 | 圖書 | 做者
具體流程
**a. 命令行建立數據庫 😗*
create database day55_bookmanager
**b. 項目配置數據庫 😗*
settings.py
下
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day55_bookmanager', 'HOST': '127.0.0.1', "PORT": 3306, "USER": 'root', 'PASSWORD': '2108' } }
**c. 用pymysql替換MYSQLdb模塊 😗*
**項目下 __init.py
文件 😗*
import pymysql pymysql.install_as_MySQLdb()
**d. app下建立表結構 😗*
**modes.py
文件下 😗*
from django.db import models class Publisher(models.Model): # AutoField -自增加類型,映射到數據庫中是11位的整數,使用此字段時,必須傳遞primary_key=True, # 不然在生成遷移腳本文件時,就會報錯 pid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) def __str__(self): # 幫助打印對象中具體的屬性值 return "{}{}".format(self.pid,self.name)
**e. 執行創數據庫遷移的命令 😗*
pycharm的Teminal命令窗口下 : 1. python manage.py makemigrations # 記錄下models.py的變動記錄並更新到 migrations 文件夾下001_inittal.py文件中 2. python manage.py migrate # 把變動記錄同步到數據庫中 這樣上面的數據庫表結構就寫入數據庫了
給表添加一些數據
A.urls.py
寫對應關係:
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/', views.publisher_list), ]
**B.app
中views.py
寫業務邏輯 😗*
from django.shortcuts import render from app01 import models def publisher_list(request): # 從數據庫中查詢全部的出版社 all_pubilshers = models.Publisher.objects.all() # 獲取數據庫所有數據,返回的是一個對象列表 # 返回一個頁面 return render(request,'publisher_list.html',{'xxx':all_pubilshers}) # xxx爲自定義的key,在前端頁面用固定格式 :{{xxx}} 能夠引用xxxkey的值all_pubilshers
C.publisher_list.html
圖書管理網頁
<table border="1"> <thead> <!-- 表頭 --> <tr> <!-- 一行 --> <th>序號</th> <th>ID</th> <th>出版社名稱</th> </tr> </thead> <tbody> <!-- 主體內容 --> {% for publisher in xxx%} <!-- 循環語句 xxx爲後端數據庫的全部數據--> <tr> <td>{{ forloop.counter }}</td> <!--forloop.counter 爲for循環次數計數 對應序號--> <td>{{ publisher.pid }}</td> <!--pid等同於pk (primarykey)--> <td>{{ publisher.name }}</td> </tr> {% endfor %} <!-- 閉合語句 --> </tbody> </table>
**數據庫修改惟一 😗*
from django.db import models class Publisher(models.Model): # AutoField -自增加類型,映射到數據庫中是11位的整數,使用此字段時,必須傳遞primary_key=True, # 不然在生成遷移腳本文件時,就會報錯 pid = models.AutoField(primary_key=True) name = models.CharField(max_length=32,unique=True) # 惟一 def __str__(self): #幫助打印對象中具體的屬性值 return "{}{}".format(self.pid,self.name) 執行創數據庫遷移的命令 : pycharm的Teminal命令窗口下 : 1. python manage.py makemigrations # 記錄下models.py的變動記錄並更新到 migrations 文件夾下001_inittal.py文件中 2. python manage.py migrate # 把變動記錄同步到數據庫中 這樣上面的數據庫表結構就寫入數據庫了
提交新增圖書頁面
<body> <form action="" method="post"> <p> 請輸入新增出版社名稱 : <input type="text" name="pub_name" value="{{ pub_name }}"> <span style="color: red">{{ error }}</span> </p> <button>提交</button> </form> </body>
展現頁面
<body> <table border="1"> <thead> <!-- 表頭 --> <tr> <!-- 一行 --> <th>序號</th> <th>ID</th> <th>出版社名稱</th> </tr> </thead> <tbody> <!-- 主體內容 --> {% for publisher in xxx%} <!-- 循環語句 xxx爲後端數據庫的全部數據--> <tr> <td>{{ forloop.counter }}</td> <!--forloop.counter 爲for循環次數計數 對應序號--> <td>{{ publisher.pid }}</td> <!--pid等同於pk (primarykey)--> <td>{{ publisher.name }}</td> </tr> {% endfor %} <!-- 閉合語句 --> </tbody> </table> <a href="/publisher_add/"><button>添加</button></a> <!--<a href="/" ></a> 表示連接到網站根目錄. <a href="/porducts/" ></a> 表示連接到根目錄下的products目錄.--> </body>
app
中views.py
寫業務邏輯
def publisher_add(requset): pub_name,error = '', '' if requset.method == "POST": # 獲取用戶提交的信息 (出版社名字) pub_name = requset.POST.get('pub_name') if not pub_name: # 輸入爲空 error = "輸入不能爲空" elif models.Publisher.objects.filter(name=pub_name): # 數據已經存在 error = "數據已經存在" else: # 用戶輸入正確,數據寫入數據庫 # 方式一 : models.Publisher.objects.create(name=pub_name) # 方式二 : # obj = models.Publisher(name = pub_name) # 在內存中實例化對象 # obj.save() # 跳轉到展現頁面 return redirect('/publisher_list/') return render(requset,'publisher_add.html',{'pub_name':pub_name,'error':error})
urls.py
寫對應關係
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/', views.publisher_list), url(r'^publisher_add/', views.publisher_add), ]
在以前基礎上須要修改的
展現界面添加操做相關按鈕
<body> <table border="1"> <thead> <!-- 表頭 --> <tr> <!-- 一行 --> <th>序號</th> <th>ID</th> <th>出版社名稱</th> <th>操做</th> </tr> </thead> <tbody> <!-- 主體內容 --> {% for publisher in xxx%} <!-- 循環語句 xxx爲後端數據庫的全部數據--> <tr> <td>{{ forloop.counter }}</td> <!--forloop.counter 爲for循環次數計數 對應序號--> <td>{{ publisher.pid }}</td> <!--pid等同於pk (primarykey)--> <td>{{ publisher.name }}</td> <td><a href="/publisher_del/?pk={{ publisher.pk }}"><button>刪除</button></a></td> </tr> {% endfor %} <!-- 閉合語句 --> </tbody> </table> <a href="/publisher_add/"><button>添加</button></a> </body>
urls.py
寫對應關係
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/', views.publisher_list), url(r'^publisher_add/', views.publisher_add), url(r'^publisher_del/', views.publisher_del), ]
views.py
增長定義函數,寫業務邏輯代碼
# 刪除數據 def publisher_del(request): # 利用get請求拿到要刪除的數據id pk = request.GET.get('pk') # 驗證要刪除的數據是否存在 query = models.Publisher.objects.filter(pid=pk) if not query : # 數據不存在返回一個字符串 return HttpResponse('要刪除的數據不存在') # 經過queryset刪除查到的全部數據 # 刪除方式一 : query.delete() # # 刪除方式二 刪除一個對象: # query[0].delete() # 跳轉到展現頁面 return redirect('/publisher_list/')
編輯頁面
<body> <form action="" method="post"> <p> 請輸入編輯出版社的新名稱 : <input type="text" name="pub_name" value="{{ obj.name }}"> <span style="color: red">{{ error }}</span> </p> <button>提交</button> </form> </body>
展現界面添加操做相關按鈕
<body> <table border="1"> <thead> <!-- 表頭 --> <tr> <!-- 一行 --> <th>序號</th> <th>ID</th> <th>出版社名稱</th> <th>操做</th> </tr> </thead> <tbody> <!-- 主體內容 --> {% for publisher in xxx%} <!-- 循環語句 xxx爲後端數據庫的全部數據--> <tr> <td>{{ forloop.counter }}</td> <!--forloop.counter 爲for循環次數計數 對應序號--> <td>{{ publisher.pid }}</td> <!--pid等同於pk (primarykey)--> <td>{{ publisher.name }}</td> <td><a href="/publisher_del/?pk={{ publisher.pk }}"><button>刪除</button></a> <a href="/publisher_edit/?pk={{ publisher.pk }}"><button>編輯</button></a> </td> </tr> {% endfor %} <!-- 閉合語句 --> </tbody> </table> <a href="/publisher_add/"><button>添加</button></a> </body>
urls.py
寫對應關係
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/', views.publisher_list), url(r'^publisher_add/', views.publisher_add), url(r'^publisher_del/', views.publisher_del), url(r'^publisher_edit/', views.publisher_edit), ]
views.py
增長定義函數,寫業務邏輯代碼
# 編輯數據 def publisher_edit(request): error = '' # 獲取要查詢的ID pk = request.GET.get('pk') # 查詢要編輯的對象 obj = models.Publisher.objects.filter(pk =pk).first() # 獲取對象列表的第一個對象 if not obj: return HttpResponse('要編輯的對象不存在') if request.method == "POST": # 獲取新提交的數據 pub_name = request.POST.get('pub_name') if not pub_name: # 輸入爲空 error = "輸入不能爲空" elif models.Publisher.objects.filter(name=pub_name): # 數據已經存在 error = "數據已經存在" else: # 編輯原始數據 obj.name = pub_name obj.save() # 跳轉到展現頁面 return redirect('/publisher_list/') return render(request,'publisher_edit.html',{'obj':obj,'error':error})
get : 發get請求的方式: 1. form表單 不指定method 2. 在地址欄中直接輸入地址 回車 3. a標題 ?k1=v1&k2=v2 request.GET request.GET.get('k1') post : form表單 method='post' request.POST request.POST.get('k1')
面向對象和關係型數據庫的一種映射 對應關係: 類 ——》 表 對象 ——》 記錄 (數據行) 屬性 ——》 字段 from app import models 查詢: models.Publisher.objects.get(name='xxxxx') # 查詢一個對象 有且惟一 差很少或者多個就報錯 models.Publisher.objects.filter(name='xxxxx') # 查詢知足條件全部對象 對象列表 queryset models.Publisher.objects.all() # 查詢全部的數據 對象列表 queryset 新增: models.Publisher.objects.create(name='xxxxx') # 返回值 就是新建的對象 obj = models.Publisher(name='xxxxx') obj.save() 刪除: models.Publisher.objects.filter(pk=1) .delete() obj = models.Publisher.objects.filter(pk=1) .first() obj.delete() 修改: obj = models.Publisher.objects.filter(pk=1) .first() obj.name = 'xxxxx' obj.save()
一對多的對應關係 - 外鍵建立在多的一方
class Book(models.Model): title = models.CharField(max_length=32) pid = models.ForeignKey('Publisher', on_delete=models.CASCADE) # 外鍵 Publisher爲對應關聯的表 # on_delete django2.0中 必填
on_delete參數的各個值的含義:
1. on_delete=None, # 刪除關聯表中的數據時,當前表與其關聯的field的行爲 2. on_delete=models.CASCADE, # 刪除關聯數據,與之關聯也刪除 - 級聯刪除 3. on_delete=models.DO_NOTHING, # 刪除關聯數據,什麼也不作 4. on_delete=models.PROTECT, # 刪除關聯數據,引起錯誤ProtectedError models.ForeignKey('關聯表', on_delete=models.SET_NULL, blank=True, null=True) 5. on_delete=models.SET_NULL, # 刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空,一對一同理) models.ForeignKey('關聯表', on_delete=models.SET_DEFAULT, default='默認值') 6. on_delete=models.SET_DEFAULT, # 刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值,一對一同理) 7. on_delete=models.SET, # 刪除關聯數據, a. 與之關聯的值設置爲指定值,設置:models.SET(值) b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象)
查詢:
all_books = models.Book.objects.all() print(all_books) for book in all_books: print(book) print(book.pk) print(book.title) print(book.pub,type(book.pub)) # book.pub爲所關聯的對象 print(book.pub_id,type(book.pub_id)) # 所關聯的對象的pk
**新增 😗*
models.Book.objects.create(title=title,pub=models.Publisher.objects.get(pk=pub_id)) models.Book.objects.create(title=title, pub_id=pub_id)
**刪除 😗*
pk = request.GET.get('pk') models.Book.objects.filter(pk=pk).delete()
**編輯 😗*
book_obj.title = title book_obj.pub_id = pub_id # book_obj.pub = models.Publisher.objects.get(pk=pub_id) book_obj.save()
class Book(models.Model): title = models.CharField(max_length=32) pid = models.ForeignKey('Publisher',on_delete=models.CASCADE) class Author(models.Model): name = models.CharField(max_length=32) book = models.ManyToManyField('Book') # 描述多對的關係 不生成此字段,而是生成Author-Book的關係表
all_authors = models.Author.objects.all().order_by('id') for author in all_authors: print(author.name) print(author.pk) print(author.books) # 關係管理對象 print(author.books.all()) # 所關聯的全部對象
models.py : class Book(models.Model): title = models.CharField(max_length=32) pid = models.ForeignKey('Publisher',on_delete=models.CASCADE) def __repr__(self): return self.title __str__ = __repr__ class Author(models.Model): name = models.CharField(max_length=32) book = models.ManyToManyField('Book') # 描述多對的關係 不生成此字段,而是生成Author-Book的關係表
author.html頁面 : <tr> <td>{{ forloop.counter }}</td> <td>{{ author.pk }}</td> <td>{{ author.name }}</td> <td>{% for book in author.book.all %} {{ book }} {% endfor %}</td>
views.py 邏輯 def author_list(request): all_author = models.Author.objects.all() return render(request, 'author_list.html', {'all_author': all_author})
books = request.POST.getlist('books') # 獲取多個元素 # 新建做者 author_obj = models.Author.objects.create(name=name) # 給做者和書籍綁定關係 author_obj.books.set(books) #
建立多對多的表的方法
django經過ManyToManyField自動建立第三張表
class Book(models.Model): title = models.CharField(max_length=32) pub = models.ForeignKey('Publisher', on_delete=models.CASCADE) # authors = models.ManyToManyField('Author') # 描述多對多的關係 不生成字段 生成關係表 def __repr__(self): return self.title __str__ = __repr__ class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book') # 描述多對多的關係 不生成字段 生成關係表
本身手動建立
class Book(models.Model): title = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) class Book_Author(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) author = models.ForeignKey(Author, on_delete=models.CASCADE) date = models.DateField()
本身建立 + ManyToManyField
class Book(models.Model): title = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField(Book, through='Book_Author') class Book_Author(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) author = models.ForeignKey(Author, on_delete=models.CASCADE) date = models.DateField()
nodels
<form class="form-inline" method="post"> <div class="form-group"> <input type="text" class="form-control" id="exampleInputEmail3" name="author_name" placeholder="{{ author_obj.name }}"> <span style="color: crimson">{{ error }}</span> 著做 :<select name="book_id" multiple> {% for book in all_books %} {% if book in author_obj.book.all %} <option selected value="{{ book.pk }}">{{ book.title }}</option> {% else %} <option value="{{ book.pk }}">{{ book.title }}</option> {% endif %} {% endfor %} </select> </div> <button type="submit" class="btn btn-default">提交</button> </form>
views
def author_list(request): all_author = models.Author.objects.all() return render(request, 'author_list.html', {'all_author': all_author})
html
<table class="table table-striped table table-hover"> <thead> <tr> <th>序號</th> <th>ID</th> <th>做者</th> <th>著做</th> <th>操做</th> </tr> </thead> <tbody> {% for author in all_author %} <tr> <td>{{ forloop.counter }}</td> <td>{{ author.pk }}</td> <td>{{ author.name }}</td> <td>{% for book in author.book.all %} 《{{ book }}》 {% endfor %}</td> <td><a href="/author_del/?pk={{ author.pk }}" class="btn btn-danger">刪除</a> <a href="/author_edit/?pk={{ author.pk}}" class="btn btn-warning">編輯</a></td> </tr> {% endfor %} </tbody> </table>
views
def author_del(request): pk = request.GET.get('pk') obj_author = models.Author.objects.filter(pk=pk) obj_author.delete() return redirect('/author_list/')
views
def author_add(request): error = '' if request.method == "POST": author_name = request.POST.get('author_name') book = request.POST.getlist('list_book') if not author_name or not book: error = '輸入或選擇不能爲空!' elif models.Author.objects.filter(name=author_name): error = '做者已存在!' else: author_obj = models.Author.objects.create(name=author_name) author_obj.book.set(book) return redirect('/author_list/') all_books = models.Book.objects.all() return render(request, 'author_add.html', {'all_books': all_books, 'error': error})
html
<form class="form-inline" method="post"> <div class="form-group"> <input type="text" class="form-control" id="exampleInputEmail3" name="author_name" placeholder="請填寫做者"> <span style="color: crimson">{{ error }}</span> 著做: <select name="list_book" multiple> {% for book in all_books %} <option value="{{ book.pk }}">{{ book.title }}</option> {% endfor %} </select> </div> <button type="submit" class="btn btn-default">提交</button> </form>
views
def author_edit(request): error = '' pk = request.GET.get('pk') author_obj = models.Author.objects.filter(pk=pk).first() if not models.Author.objects.filter(pk=pk): return HttpResponse('數據不合法!') if request.method == "POST": author_name = request.POST.get('author_name') book_id = request.POST.getlist('book_id') if not author_name or not book_id: error = '輸入或選擇不能爲空' elif models.Author.objects.filter(name=author_name): error = '做者已存在!' else: author_obj.name = author_name author_obj.save() author_obj.book.set(book_id) return redirect('/author_list/') all_books = models.Book.objects.all() return render(request, 'author_edit.html', {'all_books': all_books, 'error': error, 'author_obj': author_obj})
html
<form class="form-inline" method="post"> <div class="form-group"> <input type="text" class="form-control" id="exampleInputEmail3" name="author_name" placeholder="{{ author_obj.name }}"> <span style="color: crimson">{{ error }}</span> 著做 :<select name="book_id" multiple> {% for book in all_books %} {% if book in author_obj.book.all %} <option selected value="{{ book.pk }}">{{ book.title }}</option> {% else %} <option value="{{ book.pk }}">{{ book.title }}</option> {% endif %} {% endfor %} </select> </div> <button type="submit" class="btn btn-default">提交</button> </form>
MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典範,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯彙集到一個部件裏面,在改進和個性化定製界面及用戶交互的同時,不須要從新編寫業務邏輯。具備耦合性低、重用性高、生命週期成本低等優勢。
1. Model (模型): 核心的"數據層"(Model),也就是程序須要操做的數據或信息。 2. View (視圖): 直接面向最終用戶的"視圖層"(View)。它是提供給用戶的操做界面,是程序的外殼。 3. Controller (控制層) : 是"控制層"(Controller),它負責根據用戶從"視圖層"輸入的指令,選取"數據層"中的數據,而後對其進行相應的操做,產生最終結果。
MTV 是Django定義的一種開發規範
Model(模型):負責業務對象與數據庫的對象(ORM) Template(模版):負責如何把頁面展現給用戶 View(視圖):負責業務邏輯,並在適當的時候調用Model和Template
{{ }}和 {% %} {{ }}表示變量,在模板渲染的時候替換成值,{% %}表示邏輯相關的操做。
{{ 變量名 }} 變量名由字母數字和下劃線組成。 點(.)在模板語言中有特殊的含義,用來獲取對象的相應屬性值。
views.py中的數據: context = { "filter_list": ['西遊記', '水滸傳', '紅樓夢', '三國演義'], "filter_dict": { 'name': "小豬佩奇", 'age': 3, 'hobby': "睡覺" } } 前端頁面操做 : # 取filter_list中的第一個參數 {{ filter_list.0 }} # 西遊記 # 取字典中key的值 {{ filter_dict.name }} # 小豬佩奇 {# 取對象的name屬性 #} {{ person_list.name }} {# .操做只能調用不帶參數的方法 #} {{ person_list.dream }}
注:當模板系統遇到一個(.)時,會按照以下的順序去查詢: 1. 在字典中查詢 2. 屬性或者方法 3. 數字索引
filters - 用來修飾變量的顯示結果
語法: {{ value|filter_name:參數 }} ':'左右沒有空格沒有空格沒有空格
{{ value|default:"nothing"}} 若是value值沒傳的話就顯示nothing 注:TEMPLATES的OPTIONS能夠增長一個選項:string_if_invalid:'找不到',能夠替代default的的做用
將值格式化爲一個 「人類可讀的」 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。
{{ value|filesizeformat }}
給前端變量加參數
{{ value|add:"2" }}
{{ first|add:second }}
若是first、second都是列表
如first=[1,2,3]
,second = [4,5,6]
, 那麼結果是兩個列表的合併 :[1,2,3,4,5,6]
{{ value|lower }}
{{ value|upper}}
{{ value|title }}
{{ value|length }}
- 返回的是value的長度
{{value|slice:"2:-1"}}
{{ value|first }}
{{ value|last }}
使用字符串拼接列表。同python的str.join(list)。 {{ value|join:" // " }}
truncatewords - 按照單詞截斷
若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。
參數:截斷的字符數 {{ value|truncatechars:9}}
日期格式化 {{ value|date:"Y-m-d H:i:s"}}
views.py中 import datetime context{ 'now':datetime.datetime.now(), } {{ now|date:"Y-m-d H:i:s"}}
settings的配置: USE_L10N = False DATETIME_FORMAT = 'Y-m-d H:i:s' DATE_FORMAT = 'Y-m-d' TIME_FORMAT = 'H:i:s'
**在先後端傳輸變量數據的時候,前端引用的後端的多是一串前端代碼,在默認的狀況下,爲了安全,前端會轉義成字符串, 若是想要運行這串引用的代碼,就須要加safe {{ value|safe}}**
在py後臺中先解除不安全
from django.utils.safestring import mark_safe # 導入模塊 'a':mark_safe('<a href="http://www.baidu.com">跳轉</a>') # 定義數據的時候用mark_safe(數據)
1. 在app下建立名字必須爲 templatetags 的python包 2. 在templatetags包內建立python文件 : from django import template # 導入模板 register = template.Library() # register 爲固定寫法,不能變 # 寫過濾器 @register.filter # 必須加裝飾器 def 過濾器名(value,arg=None): # 至多能夠接收兩個參數,一個是value變量,一個是過濾器的參數(:後面的參數) return value.upper() # 變成大寫 3. 前端頁面寫法 {% load python文件 %} # 加載過濾器 {{ value|過濾器名 }}
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% endfor %} </ul>
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% empty %} <li>空的數據</li> {% endfor %} </ul> <!--若for循環取不到值,則會執行empty中的內容-->
{% num|divisibleby:2 %} <!-- 對num取2的餘數-->
{% if age<18 %} 未成年 {% elif age<30 %} 青年人 {% else %} 中年人 {% endif %}
**if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷 **
且 if 不支持算數運算、不支持連續判斷
定義中間變量 , 給變量起別名
方式一 : {% with 舊名字 as 新的名字 %} 這裏就能夠引用新的名字 {% endwith %} 方式二 : {% with 新的名字=舊名字 %} 這裏就能夠引用新的名字 {% endwith %}
這個標籤用於跨站請求僞造保護。
在頁面的form表單裏面寫上 {% csrf_token %}
下面的表格模擬html模板 ( 假設這個頁面叫 " 模板.html " )
固定頁面 | 固定頁面 |
---|---|
固定頁面 | '' 須要替換的頁面 '' content 爲這個模塊的名稱 content{% block content %} {% endblock %} |
{ % extends '模板.html'%} <!-- 導入模板--> { % block 模塊名% } <!-- 這裏的模塊麼要和模板的模塊名一致--> 這裏寫本身的內容 { % endblock% }
若是子頁面要單獨用一個樣式css 或js,
那麼就能夠單獨的使用block塊引用,避免其餘子頁面的時候也加載了沒必要要的樣式
在主界面須要插入小組件的地方如 導航欄等 寫入代碼{%include '組件名.html%}
組件名.html 中,不須要head,body等,能夠直接寫代碼
動態獲取static別名
**方式一 😗*
{% load stati %} 加載動態static別名 <!--這樣不管配置中的static別名設置成什麼,均可以用static動態獲取到 --> <!--引用文件直接在{%staticc 'css/xxcss' %} --> 例 : <link rel="stylesheet" href="{% static 'css/dashboard.css' %}">
**方式二 😗*
{% load stati %} <!--獲取動態文件前綴 { % get_static_prefix %} - 找到動態文件別名--> 例 : <link rel="stylesheet" href="{% get_static_prefix %}css/cssyangs.css">
在templatetags中的py文件中 from django import template register = template.Library() @register.simple_tag def join_str(*args, **kwargs): return '_'join(args) + "*".join(kwargs.values()) 前端頁面引用 : {% load my_tags %} # my_tags 爲 emplatetags 的py文件 {% join_str 'v1' 'v2' k3='k3' k4='v4' %} # 結果 : v1_v2k3*k4
在app中建立名字爲templatetags
的python包
在templatetags中出建立python文件my_tags.py
在建立的python中寫自定義函數
from django import template register = template.Library() @register.inclusion_tag('html模板.html') def page(num): return {'num':range(1,num+1)} # 返回的必須是個字典 會把num傳到html模板.html
新建HTML,寫分頁模板
<nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {% for i in num %} <li><a href="#">{{i}}</a></li> {% endfor %} <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav>
在須要分頁的頁面導入分頁小組件
{% load my_tags %} # 加載自定義模塊my_tags {% page 5 %} # 會把5這個參數傳回到函數中,表示的是分5頁