目錄html
一對多 多對多 一對一 # 如何判斷 換位思考 以圖書管理管理系統 圖書表 圖書和出版社是一對多的外鍵關係 一對多外鍵關係 外鍵字段建在多的那一方
一對一關係創建:author_detail = models.OneToOneField(to='AuthorDetail')前端
ForeignKey字段以及OneToOneField字段 在建立表的時候orm都會自動給該字段加_id的後綴 不管本身有沒有加 class Author(models.Model): name = models.CharField(max_length=32) phone = models.BigIntegerField() # 一對一外鍵關係創建 author_detail = models.OneToOneField(to='AuthorDetail')
多對多關係創建:authors = models.ManyToManyField(to='Author')python
class Book(models.Model): # id是自動建立的 咱們就不寫了 title = models.CharField(max_length=64) # price爲小數字段 總共8位小數位佔2位 price = models.DecimalField(max_digits=8,decimal_places=2) # 書籍與出版社 是一對多外鍵關係 publish = models.ForeignKey(to='Publish') # 默認關聯字段就是出版社表的主鍵字段 # publish = models.ForeignKey(to=Publish) # to後面也能夠直接寫表的變量名 可是須要保證該變量名在當前位置的上方出現 # 書籍與做者 是多對多外鍵關係 authors = models.ManyToManyField(to='Author') # 書籍和做者是多對多關係
一對多關係創建:publish = models.ForeignKey(to='Publish')git
class Book(models.Model): # id是自動建立的 咱們就不寫了 title = models.CharField(max_length=64) # price爲小數字段 總共8位小數位佔2位 price = models.DecimalField(max_digits=8,decimal_places=2) # 書籍與出版社 是一對多外鍵關係 publish = models.ForeignKey(to='Publish') # 默認關聯字段就是出版社表的主鍵字段 # publish = models.ForeignKey(to=Publish) # to後面也能夠直接寫表的變量名 可是須要保證該變量名在當前位置的上方出現
路由匹配 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'test',views.test), url(r'testadd',views.testadd) ] url方法第一個參數是一個正則表達式 路由匹配按照正則匹配 一旦正則可以匹配到內容 會馬上執行對應的視圖函數 不會再繼續匹配了
用戶輸入url不加最後的斜槓 django會默認自動加上 你能夠在配置文件中指定是否開啓該功能 APPEND_SLASH = True/False
無名分組 在路由匹配的時候給某段正則表達式加了括號 匹配的時候會將括號內正則表達式匹配到的內容當作位置參數傳遞給對應的視圖函數 # 無名分組 url(r'^test/([0-9]{4})/',views.test) # 視圖函數 def index(request,args): return HttpResponse('')
有名分組 給一段正則表達式起一個別名 匹配的時候會將括號內正則表達式匹配到的內容當作關鍵字參數傳遞給對應的視圖函數 # 有名分組 url(r'^test/(?P<year>\d+)/',views.test) # 視圖函數 def index(request,year): ... 補充: # 無名有名可否混合使用 >>> 不能!!! # url(r'^test/(\d+)/(?P<year>\d+)/', views.test), # 雖然不能混合使用 可是同一種命名方式 可使用多個 # url(r'^test/(\d+)/(\d+)/',views.test), url(r'^test/(?P<xxx>\d+)/(?P<year>\d+)/',views.test),
反向解析
經過一些方法 可以獲得一個結果 該結果能夠訪問到對應的url正則表達式
使用方式 先給路由與視圖函數對應關係 起一個名字 url(r'^testadd/',views.testadd,name='add') 前端解析 {% url 'add' %} 後端解析 from django.shortcuts import render,HttpResponse,redirect,reverse reverse('add')
無名分組反向解析django
# 無名分組反向解析 url(r'^testadd/(\d+)/',views.testadd,name='add') 前端解析 {% url 'add' 1 %} 後端解析 reverse('add',args=(12,))
有名分組反向解析json
# 有名分組反向解析 url(r'^testadd/(?P<year>\d+)/',views.testadd,name='add') 前端解析 {% url 'add' 1 %} # 推薦使用 {% url 'add' year= 1 %} # 標準的 後端解析 reverse('add',args=(12,)) reverse('add',kwargs={'year':12})
僞代碼詮釋 url(r'^edit_user/(\d+)/',views.edit_user,names='edit') 前端: {% for user_obj in user_queryset %} <a href="edit_user/{{ user_obj.id }}/">編輯</a> <a href="{% url 'edit' user_obj.id %}">編輯</a> {% endfor %} 後端: def edit_user(request,edit_id): reverse('edit',args=(edit_id,))
路由分發 當django項目比較龐大的時候 路由與視圖函數對應關係較多 總路由代碼太多冗長 考慮到總路由代碼很差維護 django支持每一個app均可以有本身的urls.py 而且總路由再也不作路由與視圖函數的對應關係 而僅僅只作一個分發任務的操做 根據請求的不一樣 識別出當前請求須要訪問的功能屬於哪一個app而後自動 下發到對應app裏面的urls.py中 而後由app裏面的urls.py作路由與視圖函數的匹配 不只如此每一個app除了能夠有本身的urls.py以外 還能夠有本身的static文件夾 templates模板文件 基於上面的特色 基於django分小組開發 會變得額外的簡單 每一個人只須要開發本身的app便可 以後只須要建立一個空的django項目 將多我的的app所有拷貝項目下 配置文件註冊 總路由分發一次
須要一個分發的模塊 1.總路由 from django.conf.urls import url,include # 簡寫 url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')) 2.子路由1 from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index) ] 3.子路由2 from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/',views.index) ]
爲了防止多個app路由函數的名字重複,調用的時候就用名稱空間。(不推薦)後端
推薦方式:給app路由函數起名字的時候加上前綴app的名字,這樣方式路由函數的名字就永遠不會重複了app
名稱空間(瞭解) url(r'^app01/',include('app01.urls',namespace='app01')) url(r'^app02/',include('app02.urls',namespace='app02')) 後端解析 reverse('app01:index') reverse('app02:index') 前端解析 {% url 'app01:index' %} {% url 'app02:index' %} # 在給路由與視圖函數起別名的時候只須要保證永遠不出現衝突的狀況便可 # 一般狀況下咱們推薦期別名的時候加上當前應用的應用名前綴 推薦: url(r'^index/',views.index,name='app01_index') url(r'^index/',views.index,name='app02_index')
虛擬環境 咱們想作到針對不一樣的項目 只安裝項目所須要的功能模塊 項目用不到的一律不裝 來避免加載資源時的消耗 如何建立虛擬環境 虛擬環境就相似於一個純淨的python解釋器環境 大白話 沒建立一個虛擬幻境就相似於你從新下載一個python解釋器 虛擬環境不推薦你使用太多 學習階段咱們仍是用本機的環境便可 將全部模塊所有裝到本機環境下
有view的文件就是虛擬環境函數
django版本區別 路由層 1.X用的是url 2.X、3.X用的是path url第一個參數是一個正則表達式 而path第一個參數不支持正則表達式 寫什麼就匹配什麼 若是你以爲path很差用 2.x、3.x給你提供了一個跟url同樣的功能 re_path 等價於1.x裏面的url功能 雖然path不支持正則表達式 可是它給你提供了五種默認的轉換器 str,匹配除了路徑分隔符(/)以外的非空字符串,這是默認的形式 int,匹配正整數,包含0。 slug,匹配字母、數字以及橫槓、下劃線組成的字符串。 uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。 path,匹配任何非空字符串,包含了路徑分隔符(/)(不能用?) 好比:path('login/<int:year>/',login) 除了默認的五種轉換器以外 還支持你自定義轉換器 class MonthConverter: regex='\d{2}' # 屬性名必須爲regex def to_python(self, value): return int(value) def to_url(self, value): return value # 匹配的regex是兩個數字,返回的結果也必須是兩個數字
僞靜態 url以.html結尾 給人的感受好像是這個文件是寫死的 內容不會輕易的改變 僞靜態 爲了提升你的網站被搜索引擎收藏的力度 提供網站的SEO查詢效率 可是 不管你怎麼作優化 都抗不過RMB玩家
視圖函數必需要返回一個HttpResponse對象 一個視圖函數(類),簡稱視圖,是一個簡單的Python 函數(類),它接受Web請求而且返回Web響應。 響應能夠是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片。 不管視圖自己包含什麼邏輯,都要返回響應。代碼寫在哪裏也無所謂,只要它在你當前項目目錄下面。除此以外沒有更多的要求了——能夠說「沒有什麼神奇的地方」。爲了將代碼放在某處,你們約定成俗將視圖放置在項目(project)或應用程序(app)目錄中的名爲views.py的文件中。
1.HttpResponse 返回字符串 return HttpResponse('字符串') 2.render 返回html頁面 return render(request,'templates文件夾下的html文件名',{'xxx':'hello world'}) 頁面上就能夠經過{{xxx}}拿到hello world 模板的渲染(將數據在後端按照模板語法放入html對應的位置) 3.redirect 重定向 return redirect(url) # url能夠是別人網站的全路徑 也能夠是本身網站的url後綴 return redirect('/index') return redirect('https://www.mzitu.com')
觀察源碼可知:
先後端交互的數據格式json
由於前端返回的是一個HttpResponse對象,JsonResponse對象又是HttpResponse對象的子類。 使用方法: 1.導入模塊 JsonResponse from django.http import JsonResponse 2.序列化非字典格式數據 kk=[1,2,3,4,5,'你好'] return JsonResponse(kk,safe=False) # 序列化非字典格式數據 須要將safe改成False 3.數據中的漢字不序列化 return JsonResponse(kk,safe=False,json_dumps_params={'ensure_ascii':False})
前端:
<form action="" method="post" enctype="multipart/form-data"> <input type="file" name="myfile"> <input type="submit"> </form>
後端獲取:用 FILES
def home(request): if request.method == 'POST': # 獲取用戶上傳的文件數據 print(request.FILES) file_obj = request.FILES.get('myfile') # 文件句柄,前端按鈕<input type="file" name="myfile"> print(file_obj.name) # 獲取文件名 # 保存 with open(file_obj.name,'wb') as f: for line in file_obj: f.write(line) return render(request,'home.html')