-
Web應(yīng)用
--- HTTP 請求 --->
瀏覽器 服務(wù)器
<--- HTTP 響應(yīng) ---靜態(tài)內(nèi)容:HTML頁面、CSS、JavaScript、圖像拆魏、音視頻等 ---> Nginx
動態(tài)內(nèi)容:需要通過程序自動生成的部分 ---> Python ---> 運行Python程序的服務(wù)器HTTP(s) ---> 超文本傳輸協(xié)議 ---> 使用了TCP提供的可靠傳輸服務(wù)
HTTP請求:請求行 / 請求頭 / 空行 / 消息體
HTTP響應(yīng):響應(yīng)行 / 響應(yīng)頭 / 空行 / 消息體 為什么用Python做后端開發(fā)?
~ 自動化運維 / 自動化測試 / 數(shù)據(jù)分析 / AI算法 / DevOps / SRE
~ 服務(wù)器端應(yīng)用開發(fā)(Web后端開發(fā))
---> App/網(wǎng)站的服務(wù)端代碼編寫(數(shù)據(jù)接口開發(fā))
---> 用代碼生成網(wǎng)站/App需要的動態(tài)內(nèi)容(數(shù)據(jù))
---> CGI / WSGI ---> PHP / ASP(C#) / JSP(Java)
~ Python也可以為作為服務(wù)器端應(yīng)用開發(fā)的編程語言
~ 優(yōu)點:開發(fā)效率極高(用很少的代碼可以做很多的事情)
~ 缺點:執(zhí)行效率不高(有很多公司更看重開發(fā)效率而不是執(zhí)行效率)
~ Python有很多的框架專門用于服務(wù)器端應(yīng)用開發(fā)
---> 使用框架可以減少重復(fù)代碼和基礎(chǔ)代碼的編寫
---> 程序員只需要專注于核心的業(yè)務(wù)邏輯代碼的編寫為什么選擇Django框架?
---> 源于真實的CMS系統(tǒng)的項目
---> 生態(tài)圈非常繁榮 ---> 大部分功能都有成熟的解決方案-
創(chuàng)建Django項目和實施版本控制
~ pip3 install django==2.2.12 -i https://pypi.doubanio.com/simple
~ django-admin --version
~ django-admin startproject hellodjango
~ cd hellodjango創(chuàng)建虛擬環(huán)境
~ 方法一:virtualenv --python=/usr/bin/python3 venv
~ 方法二:python3 -m venv venv激活虛擬環(huán)境
~ source venv/bin/activate ---> macOS / Linux
~ "venv/Scripts/activate" ---> Windows重建項目依賴項:
~ 有依賴項清單:pip install -r requirements.txt
~ 如果沒有依賴項清單:
- pip install django==2.2.12 mysqlclient django-redis requests
- pip freeze > requirements.txt~ git init
~ 根據(jù)需要添加版本控制忽略文件 ---> .gitginore ---> http://gitignore.io/
~ git add .
~ git commit -m '...'
~ Gitee上創(chuàng)建一個空的倉庫
~ git remote add origin 倉庫地址
~ git push -u origin master 創(chuàng)建Django應(yīng)用
~ 一個Django項目中可以包含一個或多個Django應(yīng)用
- 方法一:django-admin startapp 應(yīng)用名
- 方法二:python manage.py startapp 應(yīng)用名
~ settings.py ---> INSTALLED_APPS ---> 應(yīng)用名
補充:Django框架使用了MTV架構(gòu)模式 ---> MVC架構(gòu) ---> 數(shù)據(jù)和顯示分離
同一組數(shù)據(jù)(模型)可以展示為不同的視圖(HTML表格嘹害、ECharts圖表、Excel報表)
同一個視圖上也可以加載不同的模型進行渲染
M -----> 模型(數(shù)據(jù))-----> M
V -----> 視圖(數(shù)據(jù)的展示吮便,呈現(xiàn)給用戶看到的東西)-----> T
C -----> 控制器(連接數(shù)據(jù)和顯示的橋梁笔呀,把模型和視圖關(guān)聯(lián)起來)-----> V
~ view.py ----> 視圖函數(shù) ----> 控制器
~ models.py ----> 模型
~ templates ----> 模板 ----> 視圖
-
編寫視圖函數(shù)
~ views.py ---> 視圖函數(shù)(接收來自瀏覽器的請求,給用戶以響應(yīng))def show_index(request: HttpRequest):
return HttpResponse(content)
-
配置URL
~ 使用視圖函數(shù)需要配置URL映射(請求的路由) ---> urls.py
~ URL(統(tǒng)一資源定位符) ---> 視圖函數(shù) ---> path函數(shù)path('hello/', show_index),
path('mcode/<str:tel>/', get_mobile_code),url(r'^mcode/(?P<tel>1[3-9]\d{9})/')
def get_mobile_code(request, tel):
pass 前端渲染和后端渲染
~ 真正的項目開發(fā)中髓需,前端工程師會提供靜態(tài)頁面许师,如何讓靜態(tài)頁面上呈現(xiàn)動態(tài)內(nèi)容?僚匆?微渠?
~ 方法一:前端渲染 ---> 在瀏覽器中完成渲染操作
前端通過Ajax請求獲得后端提供的數(shù)據(jù),通過JavaScript代碼用數(shù)據(jù)渲染頁面
~ 方法二:后端渲染 ---> 在服務(wù)器端用Python程序完成
把前端提供的靜態(tài)頁改造成模板頁咧擂,把動態(tài)內(nèi)容換成占位符逞盆,通過Python程序把動態(tài)內(nèi)容填入模板頁-
編寫、配置松申、渲染模板頁
<ul id="fruits">
{% for fruit in fruits %}
<li>{{ fruit.name }}: {{ fruit.price }}<a href="">×</a></li>
{% endfor %}
</ul>TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
'APP_DIRS': True,
...
},
]render(request, 'index.html', {...}) ---> HttpResponse
-
運行Django項目
~ Django自帶的測試服務(wù)器 ---> 不能用于生產(chǎn)環(huán)境
~ python manage.py runserverWeb Server Gateway Interface
Nginx / Apache --- wsgi ---> 實現(xiàn)了WSGI的服務(wù)器
支持WSGI協(xié)議的服務(wù)器就可以運行Python項目
~ uWSGI / Gunicorn Django框架中內(nèi)置了ORM功能
~ ORM:對象關(guān)系映射 Object-Relational Mapping
Python程序 ----------------------> 關(guān)系型數(shù)據(jù)庫
對象模型 -----對象持久化到數(shù)據(jù)庫-----> 關(guān)系模型
對象模型 <----從數(shù)據(jù)庫中獲取數(shù)據(jù)------ 關(guān)系模型
class Subject(models.Model):
~ AutoField / IntegerField / DecimalField / DateTimeField
~ CharField / ImageField / FileField / BooleanField
~ OneToOneField / ForeignKey / ManyToManyField
~ 新增:Subject(...).save()
~ 查詢:Subject.objects.all() / Subject.objects.filter() ---> QuerySet
~ 查詢:Subject.objects.get() / Subject.objects.filter().first() ---> Subject
~ 排序:order_by()
~ 分頁:[:] ---> Paginator ---> get_page() ---> Page
~ objects_list / has_prev / has_next / number
~ 分組和聚合:annotate() / aggregate()
~ 多條件組合篩選:Q對象
- Q & Q / Q | Q / ~Q
~ 更新:subject ---> subject.name = '...' ---> subject.save()
- F對象:queryset ---> update(字段=F('字段名') + 100)
~ 刪除:subject ---> subject.delete()-
Django模型管理后臺
~ python manage.py createsuperuser
~ 將模型注冊到管理后臺 ---> admin.py
admin.site.register(模型, 模型管理類)django-jet
返回JSON格式數(shù)據(jù)
JavaScript Object Notation ---> JavaScript創(chuàng)建對象的字面量語法 ---> 數(shù)據(jù)交換格式
Python字典 ---> JSON字符串
ujson ---> ultra json ---> C
~ 方法一:ujson.dumps(字典) ---> JSON字符串 ---> HttpResponse ---> application/json
~ 方法二:JsonResponse(字典) ---> JSON格式數(shù)據(jù)-
從請求中獲取信息
HttpRequest
~ 獲取請求參數(shù):GET / POST / FILES / data
~ 獲取請求路徑: path / get_full_path_info()
~ 獲取請求方法:method
~ 獲取請求頭:META / COOKIES
~ 判斷是不是異步請求:is_ajax()
~ 獲取帶簽名的cookie:get_signed_cookie()
HttpResponse
~ 響應(yīng)狀態(tài)碼:status_code
~ 響應(yīng)字符集:charset
~ 響應(yīng)頭:
- response['content-type']
- response['content-disposition']
~ set_cookie() / delete_cookie() / set_signed_cookie()用戶跟蹤:記住用戶才能提供更好的更個性化的服務(wù) ---> 瀏覽器本地存儲
~ cookie
~ localStorage / sessionStorage
~ IndexDB -
表單和跨站請求偽造
CSRF ---> Cross Site Request Forgery ---> 跨站請求偽造/釣魚網(wǎng)站Django框架通過在表單添加隨機令牌的方式來解決CSRF問題
{% csrf_token %}
<input type="hidden" name="csrfmiddlewaretoken" value="...">
如果沒有提供有效的隨機令牌云芦,Django框架會阻止表單提交,響應(yīng)狀態(tài)碼403@csrf_exempt ---> 視圖函數(shù)免除CSRF令牌的裝飾器
數(shù)據(jù)庫決不能放用戶密碼的原始數(shù)據(jù) ---> 摘要/簽名/指紋
hashlib ---> md5 / sha1 / sha256
sha256() ---> update(...) ---> hexdigest()
彩虹表攻擊 ---> 反向查字典破解弱口令
如果你的網(wǎng)站允許用戶使用弱口令攻臀,那么一定要通過加鹽的方式把弱口令變成強口令再生成摘要
鹽的值只有部署系統(tǒng)的管理員才知道(程序員和DBA都不知道)-
服務(wù)器如何保留用戶狀態(tài) ---> 用戶跟蹤
服務(wù)器如果能記住用戶焕数,記住用戶的使用偏好,就能夠更好的為用戶提供服務(wù)
request.session ---> 保存在服務(wù)端的一個類似于字典的對象
瀏覽器同時還是用了本地存儲技術(shù) ---> cookie ---> 用戶身份信息(sessionid)
---> HTTP請求頭會攜帶本網(wǎng)站的cookie信息 ---> sessionid --->
和用戶關(guān)聯(lián)的那個session對象 ---> 獲取之前保存在session中的數(shù)據(jù) ---> 用戶跟蹤瀏覽器實現(xiàn)本地存儲有多種方案:
~ cookie(使用起來最簡單刨啸,瀏覽器兼容性最好)
~ localStorage / sessionStorage
~ IndexDBrequest.session['...'] = ...
python manage.py clearsessions
-
Django項目接入Redis實現(xiàn)緩存服務(wù)
memcached ---> Redis ---> Django接入Redis
pip install django-redisCACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://主機:端口/0',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'PASSWORD': 'Redis口令'
}
}
}SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default' -
導(dǎo)出Excel文件
Office 2010 ---> Excel 2010 ---> openpyxl
Office 2003 ---> Excel 2003 ---> xlwt / xlrdWorkbook ---> sheet ---> sheet['A1'] ---> save()
BytesIO --- getvalue() ---> bytes ---> HttpResponse
~ content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
~ content-disposition: inline / attachment; filename=... 生成統(tǒng)計圖表
前端接入ECharts ---> 通過JavaScript實現(xiàn)圖表效果渲染
后端提供JSON數(shù)據(jù) ---> JsonResponse原生SQL查詢
django.db.transaction.get_connection() ---> Connection對象
---> cursor() ---> execute() ---> fetchone() / fetchmany() / fetchall()-
中間件(攔截過濾器)
def simple_middleware(get_response):def middleware(request, *args, **kwargs): response = get_response(request) return response return middleware
Django中間件與之前學(xué)過的裝飾器在寫法和用途上都非常接近堡赔,
通過Django項目配置文件的MIDDLEWARE可以配置使用中間件 調(diào)用三方服務(wù)(你自己無法完成的功能)
~ SDK集成 --->
- pip install alipay-python-sdk
- pip install qiniu
~ API調(diào)用 ---> URL統(tǒng)一資源定位符 ---> HTTP ---> JSON
- pip install requests
request.get(url) / requests.post(url, data={...})ORM框架調(diào)優(yōu)
~ 限制查詢字段:only / defer
~ 解決1+N查詢:select_related / prefetch_related
~ Q對象 / F對象-
Django-Debug-Toolbar
INSTALLED_APPS ---> 'debug_toolbar'MIDDLEWARE ---> 'debug_toolbar.middleware.DebugToolbarMiddleware'
DEBUG_TOOLBAR_CONFIG = {
# 引入jQuery庫
'JQUERY_URL': 'https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js',
# 工具欄是否折疊
'SHOW_COLLAPSED': True,
# 是否顯示工具欄
'SHOW_TOOLBAR_CALLBACK': lambda x: True,
}if settings.DEBUG:
import debug_toolbar
urlpatterns.insert(0, path('debug/', include(debug_toolbar.urls)))
-
日志配置
~ 級別:DEBUG < INFO < WARNING < ERROR < CRITICALLOGGING = {
'version': 1,
'disable_existing_loggers': False,
# 配置日志格式化器
'formatters': {
'simple': {
'format': '%(asctime)s %(module)s.%(funcName)s: %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
'verbose': {
'format': '%(asctime)s %(levelname)s [%(process)d-%(threadName)s] '
'%(module)s.%(funcName)s line %(lineno)d: %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
}
},
# 配置日志過濾器
'filters': {
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
# 配置日志處理器
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'filters': ['require_debug_true'],
'formatter': 'simple',
},
'file1': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': 'access.log',
'when': 'W0',
'backupCount': 12,
'formatter': 'simple',
'level': 'INFO',
},
'file2': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': 'error.log',
'when': 'D',
'backupCount': 31,
'formatter': 'verbose',
'level': 'WARNING',
},
},
# 配置日志器
'loggers': {
'django': {
'handlers': ['console', 'file1', 'file2'],
'propagate': True,
'level': 'DEBUG',
},
}
} -
其他知識點
~ DTL:Django模板語法
模板指令:
- {% if %} / {% else %} / {% endif %}
- {% for %} / {% endfor %}
過濾器:
- lower / upper / first / last / truncatewords / date/ time
/ length / pluralize / center / ljust / rjust / cut / urlencode
/ default_if_none / filesizeformat / join / slice / slugify~ 路徑參數(shù)
- Django 1.x:url(r'mcode/(?P<mobile>1[3-9]\d{9})')
- Django 2.x:path('mcode/<str:mobile>')~ base64編碼:用64個可讀文本符號表示任意二進制數(shù)據(jù)
base64.b64encode / base64.b64decode