1.2 urlpatterns
一個(gè)url實(shí)例的對象灼狰,全在根配置搞定纠永,內(nèi)部由url組成
在django2.0以下的版本中定義url組成:
url(r‘^learn/’, views.learn)
在django2.0以上版本中定義path和re_path:
from django.urls import path, re_path
path(‘learn/’, views.learn)
或
re_path(‘learn/’, views.learn) # re_path中定義的路由地址可以寫正則表達(dá)式
1.3 路由分發(fā)
在工程目錄的urls.py中編寫配置規(guī)則坡慌,分別引入各各應(yīng)用中創(chuàng)建的urls.py 文件
在django2.0以下版本中定義路由分發(fā):
from django.conf.urls import include
urlpatterns = [
url(r’^xxx/’, include(‘a(chǎn)pp.urls’))
]
在django2.0以上版本中定義路由分發(fā):
from django.urls import path, include
urlpatterns = [
path('xxx/', include('app.urls'))
或
path('xxx/', include(('應(yīng)用名.urls', '應(yīng)用名')))
]
注意:
路由配置規(guī)則注意事項(xiàng):
路由匹配時(shí)從上到下進(jìn)行遍歷,匹配到就不會繼續(xù)向后查找了
匹配的路由前方不需要加反斜杠
2. 獲取url路徑的參數(shù)
2.1 url傳遞一個(gè)參數(shù)
2.1.1 Django2.0以下版本路由匹配一個(gè)參數(shù)的規(guī)則
如果需要從url中獲取一個(gè)值惫搏,需要對正則加小括號
url(r‘^grade/(\d+)$’, views.getStudent)
注意郭赐,url匹配中添加了()取參歼争,在請求調(diào)用的函數(shù)中必須接收 def getStudent(request, classid)
2.1.2 django2.0以上版本路由匹配一個(gè)參數(shù)的規(guī)則
? django2.0以上版本中定義路由時(shí)铃慷,可以使用path方式和re_path兩種方式,如下定義以path形式定義路由展姐。path方式中定義接收參數(shù)時(shí)躁垛,可以指定接受參數(shù)的類型:
定義接收參數(shù)的語法為: <轉(zhuǎn)換器: 參數(shù)名>
定義接受參數(shù)的常用轉(zhuǎn)換器為: int,str圾笨,uuid教馆,path
例子如下:
定義接收整形的參數(shù):path('params/<int: id>/', views.params)
定義接收字符串的參數(shù):path('params/<str: name/', views.params)
定義接收uuid類型的參數(shù):path('params/<uuid: uid>/', views.params)
定義接收路徑path的參數(shù):path('params/<path: path>/', views.params)
注意:使用<轉(zhuǎn)換器:參數(shù)名>的形式進(jìn)行定義接受參數(shù)時(shí),接受的類型由轉(zhuǎn)換器指定擂达,參數(shù)的值由指定參數(shù)名接受土铺。
2.2 url傳遞多個(gè)參數(shù)
2.2.1 Django2.0以下版本路由匹配多個(gè)參數(shù)規(guī)則
- 使用正在匹配路由中的參數(shù)
如果需要獲取url路徑中的多個(gè)參數(shù),那就添加多個(gè)括號板鬓,默認(rèn)按照順序匹配路徑名字悲敷,參數(shù)順序必須固定
定義url中傳遞三個(gè)參數(shù)的地址:
url(r‘^news/(\d{4})/(\d)+/(\d+)$’, views.getNews)
實(shí)現(xiàn)方法:匹配年月日 def getNews(requests, year, month, day)
2.使用關(guān)鍵詞獲取參數(shù)
參數(shù)也可以使用關(guān)鍵字參數(shù)形式,參數(shù)順序可以任意 url(r’news/(?P\d{4})/(?P\d)+/(?P\d+)$’, views.getNews)
注意:定義路由時(shí)定義接受第一個(gè)參數(shù)的變量為year,接受第二個(gè)參數(shù)的變量為month俭令,接受第三個(gè)參數(shù)的變量為day后德,因此在視圖函數(shù)中定義接收參數(shù)的變量的順序可以隨意的定義。
2.2.2 Django2.0以上版本路由匹配多個(gè)參數(shù)的規(guī)則
定義url中傳遞三個(gè)參數(shù)的地址:
path(‘params/<int: year>/<int: month>/<int: day>/’, views.params)
或者
re_path(’params/(?P<year>\d{4})/(?P<month>\d)+/(?P<day>\d+)$’, views.getNews)
或者
re_path(‘params/(\d{4})/(\d+)/(\d+)$’, views.params)
實(shí)現(xiàn)方法:匹配年月日 def params(requests, year, month, day)
注意:定義路由時(shí)定義接受第一個(gè)參數(shù)的變量為year抄腔,接受第二個(gè)參數(shù)的變量為month瓢湃,接受第三個(gè)參數(shù)的變量為day,因此在視圖函數(shù)中定義接收參數(shù)的變量的順序可以隨意的定義赫蛇。
3. 反向解析
3.1 在模板中進(jìn)行反解析
關(guān)鍵字參數(shù){% url namespace:name key=value key1=value1 %}
在Django2.0以下版本中定義包含url的include語法::
在根urls中定義:
url(r’^apps/’, include(‘App.urls’, namespace=’app’))
在子urls中定義:
url(r’^hello/(\d+)’, views.hello, name=’sayhello’)
在Django2.0以上版本中定義包含url的include語法:
在根urls中定義:
path(’apps/’, include((‘a(chǎn)pp.urls’, 'app'), namespace=’app’))
在應(yīng)用app的子urls中定義:
path(’hello/<int:id>/’, views.hello, name=’sayhello’)
在模板中使用: ? <a href=’{% url ‘a(chǎn)pp:sayhello’ grade_id%}’> ? 其中g(shù)rade_id是參數(shù)绵患,其中參數(shù)可以使用位置參數(shù),也可以使用關(guān)鍵詞參數(shù)悟耘,和配置urls一樣
3.2 在views中使用反向解析
使用反向解析優(yōu)點(diǎn) 如果在視圖中落蝙,模板中使用硬編碼連接,在url配置發(fā)生改變時(shí),需要變更的代碼會非常多筏勒,這樣導(dǎo)致我們的代碼結(jié)構(gòu)不是很容易維護(hù)赚瘦,使用反向解析可以提高我們代碼的擴(kuò)展性和可維護(hù)性
HttpResponseRedirect(reverse(namespace:name, kwargs = {key1 : value1, key2 : value2}))
kwargs 是字典
4. 視圖
4.1 錯(cuò)誤視圖
位置:通常在應(yīng)用下的views.py中定義 錯(cuò)誤視圖: ?
404視圖(頁面沒有被找到 page not found) ?
400視圖(客戶端操作錯(cuò)誤 bad request) ?
403視圖(權(quán)限錯(cuò)誤 403 forbidden ) ?
500視圖(服務(wù)器內(nèi)部錯(cuò)誤 server error)
5.請求與響應(yīng)
5.1 HttpRequest定義
服務(wù)器在接收到http請求后,會根據(jù)報(bào)文創(chuàng)建HttpRequest對象
視圖中第一個(gè)參數(shù)就是HttpRequest對象
Django框架會進(jìn)行自己的包裝奏寨,之后傳遞給視圖
屬性:
request.FILES 獲取圖片, 文件信息
request.path 獲取路由地址
request.COOKIES 獲取cookie內(nèi)容,字典鹰服,包含了所有的COOKIES
request.session 獲取服務(wù)器中保存的session數(shù)據(jù) 類似字典病瞳,表示會話
request.GET('key') 獲取get請求傳遞的參數(shù) 沒有key會報(bào)錯(cuò),
可以加.get('key')沒有key也不會報(bào)錯(cuò)
request.POST('key') 獲取post請求傳遞的參數(shù) 沒有key會報(bào)錯(cuò),
可以加.get('key')沒有key也不會報(bào)錯(cuò)
django沒有put, patch, delete這些, 但django有另一個(gè)處理方式
方法: is_ajax() 判斷是否是ajax(),通常在移動(dòng)端和js中
5.2 響應(yīng)QueryDict類型
1)類似字典的結(jié)構(gòu)數(shù)據(jù)悲酷,與字典的區(qū)別套菜,可以存在相同的鍵
2)GET和POST都是QueryDict對象
3)QueryDict中數(shù)據(jù)獲取方式
dict[‘name’] 或者dict.get(‘name’)
獲取指定key對應(yīng)的所有值
dict.getlist(‘name’)
如下,獲取重復(fù)提交數(shù)據(jù)的方法:
5.3 響應(yīng)
1)可以直接返回一個(gè)HttpResponse對象:
服務(wù)器返回給客戶端的數(shù)據(jù)设易,HttpResponse由程序員自己創(chuàng)建
不使用模板逗柴,直接HttpResponse()
2)可以返回模板
調(diào)用模板,進(jìn)行渲染顿肺,直接使用render一步到位
返回表達(dá)式:
render(request, template_name, context)
request 請求體對象
template_name 模板路徑
context 字典參數(shù)戏溺,用來填坑
3)屬性
Content 返回的內(nèi)容
Charset 編碼格式
status_code 響應(yīng)狀態(tài)碼(200,4xx,5xx)
4xx 客戶端的錯(cuò)誤
5xx 服務(wù)端的錯(cuò)誤
content_type MIME類型,定義傳輸類型的屠尊,比如有xml旷祸,html,png等等讼昆,比如content_type=’image/jpg’
4)方法
init 初始化內(nèi)容
write(xxx) 直接寫到文本
flush 沖刷緩沖區(qū)
set_cookie(key, value=’’, max_age=None, exprise=None)
delete_cookie(key) 刪除cookie托享,上面是設(shè)置
4)重定向
HttpResponseRedirect響應(yīng)重定向:可以實(shí)現(xiàn)服務(wù)器內(nèi)部的跳轉(zhuǎn)
Return HttpResponseRedirect(‘/xxx/xxx’)
使用的時(shí)候推薦使用反向解析
JsonResponse
使用json數(shù)據(jù)的請求,通常用在異步請求上JsonResponse(dict)
content_type是application/json
========頁面截圖==========
一浸赫,我們不能將所有包的路由都放在一個(gè)路由文件中,
app包的路由就要放在app包里的urls.py文件中,
uesr包的路由就要放在user包里的urls.py文件中,
所以我們要拆分 - 路由分發(fā)
1.在主目錄的urls.py文件中,要導(dǎo)入
from django.urls import include
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
# 路由分發(fā) include里面的'user'就是路由的user/
path('user/', include(('user.urls', 'user'), namespace='user')),
# 定義namespace參數(shù) namespace='a'是代替app/ 現(xiàn)在app/這個(gè)前綴都無所謂
path('app/', include(('app.urls', 'app'), namespace='a')),
]
path('app/', include(('應(yīng)用名.urls', '應(yīng)用名'), namespace='a'))
2.在app/urls.py文件中
from django.urls import path, re_path
from app.views import *
urlpatterns = [
path('index/', index),
# 訪問index 跳轉(zhuǎn)redirect_stu
path('redirect_stu/', redirect_stu, name='red'),
path('redirect_params/<int:id>/', redirect_params, name='rep'),
# 用正則時(shí)一定要在path前加re - re_path
re_path('redirect_params_re/(\d+)/', redirect_params_re, name='reb'),
path('req/', req, name='req'),
path('res/', res, name='res'),
]
然后寫相應(yīng)的views闰围,
3.views.py文件中寫對應(yīng)的urls的函數(shù)
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render
# HttpResponseRedirect實(shí)現(xiàn)跳轉(zhuǎn)功能的
from django.urls import reverse
def index(request):
if request.method == 'GET':
# 跳轉(zhuǎn)到另外一個(gè)路由地址上
# 無參的情況下進(jìn)行跳轉(zhuǎn)
# 第一種跳轉(zhuǎn): 使用硬編碼url
# return HttpResponseRedirect('/app/redirect_stu/') # 不加/app 會報(bào)錯(cuò), 沒有寫name時(shí)
# 第二種跳轉(zhuǎn): 使用反向解析 reverse('namespace:name')
# return HttpResponseRedirect(reverse('a:red')) # 反向解析'a:red'就是namespace:name
# 有參的情況下跳轉(zhuǎn)
# return HttpResponseRedirect('/app/redirect_params/16/')
# return HttpResponseRedirect(reverse('a:rep', kwargs={'id': 18}))
# return HttpResponseRedirect(reverse('a:reb', args=(20,)))
return render(request, 'index.html')
def redirect_stu(request):
if request.method == 'GET':
# 跳轉(zhuǎn)到另外一個(gè)路由地址上 在index.html中<a href="{% url 'a:red' %}">無參跳轉(zhuǎn)
return HttpResponse('我是跳轉(zhuǎn)方法')
def redirect_params(request, id):
if request.method == 'GET':
# 跳轉(zhuǎn)到另外一個(gè)路由地址上,在index.html中{% url 'a:rep' 20 %}
return HttpResponse('帶參的跳轉(zhuǎn), 參數(shù): %s' % id)
def redirect_params_re(request, id):
if request.method == 'GET':
# 跳轉(zhuǎn)到另外一個(gè)路由地址上,在index.html中{% url 'a:reb' 20 %}
return HttpResponse('帶參的跳轉(zhuǎn)2, 參數(shù): %s' % id)
def req(request):
if request.method == 'GET':
return HttpResponse('請求')
def res(request):
if request.method == 'GET':
# 下面幾個(gè)都是響應(yīng)
# return HttpResponse('響應(yīng)')
# return HttpResponseRedirect('跳轉(zhuǎn)')
# return render()
# return JsonResponse({'code': 200})
response = HttpResponseRedirect('/app/index/')
response.set_cookie('token', 123456)
return response
2.另一個(gè)user包的路由
(裝飾器修飾等)
1.在user/urls.py中
from django.contrib.auth.decorators import login_required
from django.urls import path
from user.views import *
from utils.functions import is_login
# django自帶的登錄注冊的實(shí)現(xiàn)
urlpatterns = [
path('register/', register, name='register'),
path('login/', login, name='login'),
# 給index加裝飾器登錄才讓訪問不登陸不讓訪問
# path('index/', login_required(index), name='index'), # django自帶的
path('index/', is_login(index), name='index'),
path('logout/', login_required(logout), name='logout'),
# 使用session實(shí)現(xiàn)登錄注冊注銷功能
path('my_register/', my_register, name='my_register'),
path('my_login/', my_login, name='my_login'),
# session操作語法
path('sess/', sess_operate, name='sess_operate')
]
2./user/views.py中
from django.contrib import auth
from django.contrib.auth.hashers import make_password, check_password
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from user.models import MyUser
def register(request):
if request.method == 'GET':
return render(request, 'register.html')
if request.method == 'POST':
# 獲取數(shù)據(jù)并校驗(yàn)
username = request.POST.get('username')
password = request.POST.get('password')
password2 = request.POST.get('password2')
if username and password and password2 and password == password2:
if not User.objects.filter(username=username).exists():
# 這樣寫避免了if else 太多了不好, 盡量少用
# 保存
User.objects.create_user(username=username,
password=password)
# 跳轉(zhuǎn)
return HttpResponseRedirect(reverse('user:login'))
error = '用戶已存在, 請更換賬號'
return render(request, 'register.html', {'error': error})
else:
error = '注冊參數(shù)有誤, 請確認(rèn)'
return render(request, 'register.html', {'error': error})
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
if request.method == 'POST':
# 獲取數(shù)據(jù)
username = request.POST.get('username')
password = request.POST.get('password')
if username and password:
# 校驗(yàn)
user = auth.authenticate(username=username,
password=password)
if user:
# 設(shè)置登錄狀態(tài)
# 查看session是否變化, request.user這個(gè)東西的變化
# 變化: 開始是匿名用戶, 運(yùn)行這一步之后就顯示你寫的用戶名了
auth.login(request, user)
# auth.logout(request)
return HttpResponseRedirect(reverse('user:index'))
error = '用戶名或者密碼錯(cuò)誤'
return render(request, 'login.html', {'error': error})
else:
error = '登錄信息請?zhí)顚懲暾?
return render(request, 'login.html', {'error': error})
def index(request):
if request.method == 'GET':
# request上面綁定屬性的, 如user屬性, {{ user }}來調(diào)用
return render(request, 'index.html')
def logout(request):
if request.method == 'GET':
auth.logout(request)
return HttpResponseRedirect(reverse('user:login'))
# 不用django里面的方法
def my_register(request):
if request.method == 'GET':
return render(request, 'register.html')
if request.method == 'POST':
# 獲取數(shù)據(jù)并校驗(yàn)
username = request.POST.get('username')
password = request.POST.get('password')
password2 = request.POST.get('password2')
if username and password and password2 and password == password2:
if not MyUser.objects.filter(username=username).exists():
# 保存
pwd = make_password(password) # 將密碼加密(編碼),不然下面的密碼是明文的
MyUser.objects.create(username=username,
password=pwd)
# 跳轉(zhuǎn)
return HttpResponseRedirect(reverse('user:login'))
error = '用戶已存在, 請更換賬號'
return render(request, 'register.html', {'error': error})
else:
error = '注冊參數(shù)有誤, 請確認(rèn)'
return render(request, 'register.html', {'error': error})
def my_login(request):
if request.method == 'GET':
return render(request, 'login.html')
if request.method == 'POST':
# 獲取數(shù)據(jù)
username = request.POST.get('username')
password = request.POST.get('password')
if username and password:
# 校驗(yàn)
user = MyUser.objects.filter(username=username).first()
if user:
# 校驗(yàn)密碼
if check_password(password, user.password):
# TODO 登錄操作 m
request.session['user_id'] = user.id
return HttpResponseRedirect(reverse('user:index'))
error = '用戶名或者密碼錯(cuò)誤'
return render(request, 'login.html', {'error': error})
else:
error = '登錄信息請?zhí)顚懲暾?
return render(request, 'login.html', {'error': error})
def sess_operate(request):
if request.method == 'GET':
# 取session_key的值
session_key = request.session.session_key
print(session_key)
# TODO 退出: 1.刪除session-data(標(biāo)識符)的字段 但客戶端的數(shù)據(jù)還沒刪(刪的是數(shù)據(jù)庫的信息)
# del request.session['user_id']
# TODO 2.通過key來刪掉整個(gè)數(shù)據(jù)退出 但客戶端的數(shù)據(jù)還沒刪(刪的是數(shù)據(jù)庫的信息)
# request.session.delete(session_key)
# TODO 3.通過在客戶端刪除, 數(shù)據(jù)庫也會刪除數(shù)據(jù)
request.session.flush()
return HttpResponseRedirect('操作session數(shù)據(jù)')
3./user/models.py中 - 要用自己定義的登錄注冊先創(chuàng)建一個(gè)類
from django.db import models
class MyUser(models.Model):
username = models.CharField(max_length=10, unique=True, null=False)
password = models.CharField(max_length=255, null=False)
class Meta:
db_table = 'my_user'