1,Django 框架中新建的app應用,必定先去settings.py註冊css
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # 'app01' # 簡寫 'app01.apps.App01Config' # 全稱 ]
## 注意事項:html
2, html文件默認全都放在templates文件夾下前端
對於前段已經寫好了的文件 咱們只是拿過來使用 那麼這些文件均可以稱之爲叫"靜態文件"python
靜態文件能夠是mysql
bootstrap一類的前段框架 已經寫好了的git
圖片正則表達式
csssql
js數據庫
靜態文件默認全都放在static文件夾下django
static文件夾中默認會默認建立的子文件夾
css文件夾 當前網站全部的樣式文件
js文件 當前網站全部的js文件
img文件 當前網站全部的圖片文件
其餘(前端框架代碼 第三方插件代碼...)
啓動ddjango項目的時候 必定要確保一個端口號只有一個django項目在佔用
否則的話 會容易形成bug、
用戶能夠訪問的資源 都在url中
只有url中開設相關的資源你才能訪問到(******)
後端資源通常都須要手動指定是否須要暴露給用戶
## 3 靜態文件配置
STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static') ] ##你只要輸入static文件夾內具體文件的路徑就可以訪問到
#
STATIC_URL = '/static/' # 這個static不是文件夾的名字 而是接口前綴 """只要你想訪問靜態文件中的資源 文件路徑就必須用static開頭""" # 手動將static文件夾中全部的資源暴露給用戶 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static'), # 真正的文件夾路徑 os.path.join(BASE_DIR,'static1'), # 真正的文件夾路徑 os.path.join(BASE_DIR,'static2'), # 真正的文件夾路徑 os.path.join(BASE_DIR,'static3') # 真正的文件夾路徑 ]
##
django默認是支持自動重啓代碼的 因此你只須要多刷新幾回頁面就能夠
可是有時候它的重啓機制比較慢
機制:實時監測文件代碼變化 只要有變化 就會自動重啓
可能你的代碼尚未寫完 這個時候就會自動報錯
##
靜態文件接口前綴"動態解析"
##靜態文件接口前綴"動態解析" {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> ## 利用解析器 動態獲取接口前綴
##
重點!
form表單默認是get請求
攜帶數據的方式是url問好後跟數據
http://127.0.0.1:8000/login/?username=zekai&password=123
能夠經過method改成post請求
改爲post請求以後 須要去settings文件中註釋掉一箇中間件
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 表單提交數據的由 action 的三種方法:
1.不寫的狀況下 默認往當前地址提交
2.還能夠寫後綴/index/(將項目經常使用這種)
3.還能夠寫全路徑
##
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
# 注意事項
# 是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑的配置項 APPEND_SLASH=True
Django settings.py配置文件中默認沒有 APPEND_SLASH 這個參數,但 Django 默認這個參數爲 APPEND_SLASH = True。 其做用就是自動在網址結尾加'/'。
其效果就是:
咱們定義了urls.py:
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^blog/$', views.blog), ]
訪問 http://www.example.com/blog 時,默認將網址自動轉換爲 http://www.example/com/blog/ 。
若是在settings.py中設置了 APPEND_SLASH=False,此時咱們再請求 http://www.example.com/blog 時就會提示找不到頁面。
##
視圖函數通常主要會先處理get請求
def login(request): # 視圖函數針對不一樣的請求方式 應該有不一樣的處理邏輯 # if request.method == 'GET': # print('收到了') # print(request.method) # 可以獲取前端請求方式 而且是全大寫的字符串 # print(type(request.method)) # return render(request,'login.html') # elif request.method == 'POST': # # 獲取用戶輸入 作相應的邏輯判斷 # return HttpResponse("拿到了 老弟") if request.method == 'POST': return HttpResponse('來啦 寶貝') return render(request,'login.html')
# 獲取前端數據
在後端PY 文件中 request.method獲取請求方式: get, post
對數據的處理 不僅僅只有wsgiref模塊 django後端也進行了大量的數據處理
GET
request.GET獲取前端get提交的數據(就相似因而一個大字典)
取值
request.GET.get('username') # 雖然value是一個列表 可是默認只取列表最後一個元素
# 強烈不建議你使用中括號的形式取值
# 若是想直接把列表所有取出(******)
request.GET.getlist('hobby')
POST
request.POST獲取前端post提交的數據(就相似因而一個大字典)
取值
request.POST.get('username') # 雖然value是一個列表 可是默認只取列表最後一個元素
# 強烈不建議你使用中括號的形式取值
# 若是想直接把列表所有取出(******)
request.POST.getlist('hobby')
## 數據庫配置
django默認使用的是自帶的sqlite數據庫
若是你想讓它其餘的數據庫 須要在settings配置文件中 配置
# 1.settings文件中配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day51', 'HOST':'127.0.0.1', 'PORT':3306, 'USER':'root', 'PASSWORD':'123', 'CHARSET':'utf8' } } # 2.還要在項目名下的init文件或者是應用名下的init文件中告訴django不要使# 用默認的mysqldb鏈接mysql # 而是使用pymysql import pymysql pymysql.install_as_MySQLdb()
##
django orm
ORM 對象關係映射
表 ----- ----- 類
一條條記錄 ----- 對象
字段對應的值 --- 對象的屬性
1,模型表的創建過程:
首先須要在應用下的models.py中書寫模型類
class User(models.Model): # 將id字段設置爲User表主鍵字段 在django orm中 你能夠不寫主鍵字典 django會默認給你的表建立一個名爲id的主鍵字段 # id = models.AutoField(primary_key=True) # 一旦你本身指定了主鍵字段 那麼django就不會自動再幫你建立了 username = models.CharField(max_length=32) # username varchar(32) CharField必需要指定max_length參數 password = models.IntegerField() # password int *************************須要執行數據庫遷移(同步)命令****************************** python3 manage.py makemigrations # 僅僅是在小本本上(migrations文件夾)記錄數據庫的修改 並不會直接操做數據 python3 manage.py migrate # 將數據庫修改記錄 真正同步到數據庫
注意:只要動了models中跟數據庫相關的代碼 就必須從新執行上面的兩條命令 缺一不可!!!!
###
2,表字段的增刪改查
增
當一張表已經建立出來以後 後續還想添加字段,能夠有兩種方式
1.給新增的字段設置默認值
addr = models.CharField(max_length=32,default='China') # default該字段默認值
2.給新增的字段設置成能夠爲空
age = models.IntegerField(null=True) # 該字段容許爲空
2,刪除
刪(慎用)
刪除字段 直接在models.py中註釋該字段 而後從新執行兩條命令便可
python3 manage.py makemigrations # 僅僅是在小本本上(migrations文件夾)記錄數據庫的修改 並不會直接操做數據 python3 manage.py migrate # 將數據庫修改記錄 真正同步到數據庫
注意:執行完以後 表中該字段所對應的全部的數據所有刪除
而且通常狀況下 基本是不會用到真正意義上的刪除
3,
orm操做須要使用models中的類的名字
##數據的查 from app01 import models models.User.objects.all() # 直接拿全部的數據 models.User.objects.get(username=username) res = models.User.objects.filter(username=username) res.query
##數據的增 1. models.User.objects.create(username=username,password=password) 2. user_obj = models.User(username=username,password=password) user_obj.save() # 刪 models.User.objects.filter(條件).delete() # 改 models.User.objects.filter(條件).update()
路由層
url()方法 第一個參數 實際上是一個正則表達式
路由匹配
url(正則表達式,視圖函數內存地址)
只要正則匹配到了內容,就再也不繼續往下匹配,而是直接後面的視圖函數
匹配首頁
url(r'^$',home)
匹配尾頁
url(r'',errors)
## 路由匹配的規律
第一次按照用戶輸入什麼就匹配什麼若是匹配不上
第二次django會讓瀏覽器自動再尾部加斜槓再次匹配 還匹配不上就會報錯
上述規律不是瀏覽器的特色,是django的功能
django settings文件中
APPEND_SALSH = True # 自動加斜槓
"""爲何setting文件中變量名必須寫全大寫"""
一旦前面的正則匹配到了內容 就不會再往下繼續匹配 而是直接執行對應的視圖函數
正是因爲上面的特性 當你的項目特別龐大的時候 url的先後順序也是你須要你考慮
極有可能會出現url錯亂的狀況
django在路由的匹配的時候 當你在瀏覽器中沒有敲最後的斜槓
django會先拿着你沒有敲斜槓的結果取匹配 若是都沒有匹配上 會讓瀏覽器在末尾加斜槓再發一次請求 再匹配一次 若是還匹配不上纔會報錯
若是你想取消該機制 不想作二次匹配能夠在settings配置文件中 指定
APPEND_SLASH = False # 該參數默認是True
無名分組
url(r'^test/([0-9]{4})/', views.test)
路由匹配的時候 會將括號內正則表達式匹配到的內容 當作位置參數傳遞給視圖函數
test(request,2019)
有名分組
url(r'^test/(?P<year>\d+)/', views.test)
路由匹配的時候 會將括號內正則表達式匹配到的內容 當作關鍵字參數傳遞給視圖函數
test(request,year=2019)
# 無名有名不能混合使用 !!!
url(r'^test/(\d+)/(?P<year>\d+)/', views.test),
可是用一種分組下 可使用多個
# 無名分組支持多個
# url(r'^test/(\d+)/(\d+)/', views.test),
# 有名分組支持多個
# url(r'^test/(?P<year>\d+)/(?P<xx>\d+)/', views.test),
反向解析
本質:其實就是給你返回一個可以返回對應url的地址
1.先給url和視圖函數對應關係起別名
url(r'^index/$',views.index,name='kkk')
2.反向解析
後端反向解析
後端能夠在任意位置經過reverse反向解析出對應的url
from django.shortcuts import render,HttpResponse,redirect,reverse
reverse('kkk')
前端反向解析
{% url 'kkk' %}
無名分組反向解析
url(r'^index/(\d+)/$',views.index,name='kkk')
後端反向解析
reverse('kkk',args=(1,)) # 後面的數字一般都是數據的id值
前端反向解析
{% url 'kkk' 1%} # 後面的數字一般都是數據的id值
有名分組反向解析
同無名分組反向解析意義的用法
url(r'^index/(?P<year>\d+)/$',views.index,name='kkk')
後端方向解析
print(reverse('kkk',args=(1,))) # 推薦你使用上面這種
print(reverse('kkk',kwargs={'year':1}))
前端反向解析
<a href="{% url 'kkk' 1 %}">1</a> # 推薦你使用上面這種
<a href="{% url 'kkk' year=1 %}">1</a>
例子:
傳參數
注意:在同一個應用下 別名千萬不能重複!!!
路由分發(******)
當你的django項目特別龐大的時候 路由與視圖函數對應關係特別特別多
那麼你的總路由urls.py代碼太過冗長 不易維護
每個應用均可以有本身的urls.py,static文件夾,templates文件夾(******)
正是基於上述條件 能夠實現多人分組開發 等多人開發完成以後 咱們只須要建立一個空的django項目
而後將多人開發的app所有註冊進來 在總路由實現一個路由分發 而再也不作路由匹配(來了以後 我只給你分發到對應的app中)
當你的應用下的視圖函數特別特別多的時候 你能夠建一個views文件夾 裏面根據功能的細分再建不一樣的py文件
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')), ]
名稱空間(瞭解)
多個app起了相同的別名 這個時候用反向解析 並不會自動識別應用前綴
若是想避免這種問題的發生
方式1:
總路由
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' %}
方式2:
起別名的時候不要衝突便可 通常狀況下在起別名的時候一般建議以應用名做爲前綴
name = 'app01_index'
name = 'app02_index'
僞靜態
靜態網頁:數據是寫死的 萬年不變
僞靜態網頁的設計是爲了增長百度等搜索引擎seo查詢力度
全部的搜索引擎其實都是一個巨大的爬蟲程序
網站優化相關 經過僞靜態確實能夠提升你的網站被查詢出來的機率
可是再怎麼優化也抵不過RMB玩家
虛擬環境
通常狀況下 咱們會給每個項目 配備該項目所須要的模塊 不須要的一律不裝
虛擬環境 就相似於爲每一個項目量身定作的解釋器環境
如何建立虛擬環境
每建立一個虛擬環境 就相似於你又下載了一個全新的python解釋器
django版本的區別
django1.X跟django2.X版本區別
路由層1.X用的是url
而2.X用的是path
2.X中的path第一個參數再也不是正則表達式,而是寫什麼就匹配什麼 是精準匹配
當你使用2.X不習慣的時候 2.X還有一個叫re_path
2.x中的re_path就是你1.X的url
雖然2.X中path不支持正則表達式 可是它提供了五種默認的轉換器
1.0版本的url和2.0版本的re_path分組出來的數據都是字符串類型
默認有五個轉換器,感興趣的本身能夠課下去試一下
str,匹配除了路徑分隔符(/)以外的非空字符串,這是默認的形式
int,匹配正整數,包含0。
slug,匹配字母、數字以及橫槓、下劃線組成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路徑分隔符(/)(不能用?)
path('index/<int:id>/',index) # 會將id匹配到的內容自動轉換成整型
還支持自定義轉換器
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value 佔四位,不夠用0填滿,超了則就按超了的位數來!
register_converter(FourDigitYearConverter, 'yyyy')
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<yyyy:year>/', views.year_archive),
...
]
視圖層
1.小白必會三板斧
1.HttpResponse
2.render
3.redirect
django視圖函數必需要給返回一個HttpResponse對象
先後端分離
前端一我的幹(前端轉成自定義對象)
JSON.stringify() json.dumps()
JSON.parse() json.loads()
後端另外一個幹(python後端用字典)
只要涉及到數據交互,通常狀況下都是用的json格式
後端只負責產生接口,前端調用該接口能拿到一個大字典
後端只須要寫一個接口文檔 裏面描述字典的詳細信息以及參數的傳遞
2.JsonReponse
from django.http import JsonResponse
def index(request):
data = {'name':'jason好帥哦 我好喜歡','password':123}
l = [1,2,3,4,5,6,7,8]
# res = json.dumps(data,ensure_ascii=False)
# return HttpResponse(res)
# return JsonResponse(data,json_dumps_params={'ensure_ascii':False})
return JsonResponse(l,safe=False) # 若是返回的不是字典 只須要修改safe參數爲false便可
3.上傳文件
form表單上傳文件須要注意的事項
1.enctype須要由默認的urlencoded變成formdata
2.method須要由默認的get變成post
(目前還須要考慮的是 提交post請求須要將配置文件中的csrf中間件註釋)
form表單上傳文件
須要注意的實現
1.method必須是post
2.enctype必需要指定成formdata
3.目前須要考慮的 須要將settings配置文件中的csrf中間件註釋掉
後端再也不經過request.POST獲取文件數據,而是經過request.FILES
file_obj = request.FILES.get('myfile')
file_obj.name # 文件名
with open(file_obj.name,'wb') as f:
for chunk in file_obj.chunks():
f.write(chunk)
若是form表單上傳文件 後端須要在request.FILES獲取文件數據 而再也不是POST裏面
request.method
request.GET
request.POST
request.FILES
request.path # 只回去url後綴 不獲取?後面的參數
request.get_full_path() # 後綴和參數所有獲取