1.2 urlpatterns
一个url实例的对象,全在根配置搞定,内部由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中定义的路由地址可以写正则表达式
1.3 路由分发
在工程目录的urls.py中编写配置规则,分别引入各各应用中创建的urls.py 文件
在django2.0以下版本中定义路由分发:
from django.conf.urls import include
urlpatterns = [
url(r’^xxx/’, include(‘app.urls’))
]
在django2.0以上版本中定义路由分发:
from django.urls import path, include
urlpatterns = [
path('xxx/', include('app.urls'))
或
path('xxx/', include(('应用名.urls', '应用名')))
]
注意:
路由配置规则注意事项:
路由匹配时从上到下进行遍历,匹配到就不会继续向后查找了
匹配的路由前方不需要加反斜杠
2. 获取url路径的参数
2.1 url传递一个参数
2.1.1 Django2.0以下版本路由匹配一个参数的规则
如果需要从url中获取一个值,需要对正则加小括号
url(r‘^grade/(\d+)$’, views.getStudent)
注意,url匹配中添加了()取参,在请求调用的函数中必须接收 def getStudent(request, classid)
image.png
2.1.2 django2.0以上版本路由匹配一个参数的规则
django2.0以上版本中定义路由时,可以使用path方式和re_path两种方式,如下定义以path形式定义路由。path方式中定义接收参数时,可以指定接受参数的类型:
定义接收参数的语法为: <转换器: 参数名>
定义接受参数的常用转换器为: int,str,uuid,path
例子如下:
定义接收整形的参数:path('params/<int: id>/', views.params)
定义接收字符串的参数:path('params/<str: name/', views.params)
定义接收uuid类型的参数:path('params/<uuid: uid>/', views.params)
定义接收路径path的参数:path('params/<path: path>/', views.params)
注意:使用<转换器:参数名>的形式进行定义接受参数时,接受的类型由转换器指定,参数的值由指定参数名接受。
2.2 url传递多个参数
2.2.1 Django2.0以下版本路由匹配多个参数规则
- 使用正在匹配路由中的参数
如果需要获取url路径中的多个参数,那就添加多个括号,默认按照顺序匹配路径名字,参数顺序必须固定
定义url中传递三个参数的地址:
url(r‘^news/(\d{4})/(\d)+/(\d+)$’, views.getNews)
实现方法:匹配年月日 def getNews(requests, year, month, day)
image.png
2.使用关键词获取参数
参数也可以使用关键字参数形式,参数顺序可以任意 url(r’news/(?P\d{4})/(?P\d)+/(?P\d+)$’, views.getNews)
image.png
注意:定义路由时定义接受第一个参数的变量为year,接受第二个参数的变量为month,接受第三个参数的变量为day,因此在视图函数中定义接收参数的变量的顺序可以随意的定义。
2.2.2 Django2.0以上版本路由匹配多个参数的规则
定义url中传递三个参数的地址:
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)
实现方法:匹配年月日 def params(requests, year, month, day)
注意:定义路由时定义接受第一个参数的变量为year,接受第二个参数的变量为month,接受第三个参数的变量为day,因此在视图函数中定义接收参数的变量的顺序可以随意的定义。
3. 反向解析
3.1 在模板中进行反解析
关键字参数{% 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((‘app.urls’, 'app'), namespace=’app’))
在应用app的子urls中定义:
path(’hello/<int:id>/’, views.hello, name=’sayhello’)
在模板中使用: <a href=’{% url ‘app:sayhello’ grade_id%}’> 其中grade_id是参数,其中参数可以使用位置参数,也可以使用关键词参数,和配置urls一样
image.png
3.2 在views中使用反向解析
使用反向解析优点 如果在视图中,模板中使用硬编码连接,在url配置发生改变时,需要变更的代码会非常多,这样导致我们的代码结构不是很容易维护,使用反向解析可以提高我们代码的扩展性和可维护性
HttpResponseRedirect(reverse(namespace:name, kwargs = {key1 : value1, key2 : value2}))
kwargs 是字典
image.png
4. 视图
4.1 错误视图
位置:通常在应用下的views.py中定义 错误视图:
404视图(页面没有被找到 page not found)
400视图(客户端操作错误 bad request)
403视图(权限错误 403 forbidden )
500视图(服务器内部错误 server error)
5.请求与响应
5.1 HttpRequest定义
服务器在接收到http请求后,会根据报文创建HttpRequest对象
视图中第一个参数就是HttpRequest对象
Django框架会进行自己的包装,之后传递给视图
属性:
request.FILES 获取图片, 文件信息
request.path 获取路由地址
request.COOKIES 获取cookie内容,字典,包含了所有的COOKIES
request.session 获取服务器中保存的session数据 类似字典,表示会话
request.GET('key') 获取get请求传递的参数 没有key会报错,
可以加.get('key')没有key也不会报错
request.POST('key') 获取post请求传递的参数 没有key会报错,
可以加.get('key')没有key也不会报错
django没有put, patch, delete这些, 但django有另一个处理方式
方法: is_ajax() 判断是否是ajax(),通常在移动端和js中
5.2 响应QueryDict类型
1)类似字典的结构数据,与字典的区别,可以存在相同的键
2)GET和POST都是QueryDict对象
3)QueryDict中数据获取方式
dict[‘name’] 或者dict.get(‘name’)
获取指定key对应的所有值
dict.getlist(‘name’)
image.png
如下,获取重复提交数据的方法:
image.png
5.3 响应
1)可以直接返回一个HttpResponse对象:
服务器返回给客户端的数据,HttpResponse由程序员自己创建
不使用模板,直接HttpResponse()
2)可以返回模板
调用模板,进行渲染,直接使用render一步到位
返回表达式:
render(request, template_name, context)
request 请求体对象
template_name 模板路径
context 字典参数,用来填坑
3)属性
Content 返回的内容
Charset 编码格式
status_code 响应状态码(200,4xx,5xx)
4xx 客户端的错误
5xx 服务端的错误
content_type MIME类型,定义传输类型的,比如有xml,html,png等等,比如content_type=’image/jpg’
4)方法
init 初始化内容
write(xxx) 直接写到文本
flush 冲刷缓冲区
set_cookie(key, value=’’, max_age=None, exprise=None)
delete_cookie(key) 删除cookie,上面是设置
4)重定向
HttpResponseRedirect响应重定向:可以实现服务器内部的跳转
Return HttpResponseRedirect(‘/xxx/xxx’)
使用的时候推荐使用反向解析
JsonResponse
使用json数据的请求,通常用在异步请求上JsonResponse(dict)
content_type是application/json
========页面截图==========
一,我们不能将所有包的路由都放在一个路由文件中,
app包的路由就要放在app包里的urls.py文件中,
uesr包的路由就要放在user包里的urls.py文件中,
所以我们要拆分 - 路由分发
1.在主目录的urls.py文件中,要导入
from django.urls import include
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
# 路由分发 include里面的'user'就是路由的user/
path('user/', include(('user.urls', 'user'), namespace='user')),
# 定义namespace参数 namespace='a'是代替app/ 现在app/这个前缀都无所谓
path('app/', include(('app.urls', 'app'), namespace='a')),
]
path('app/', include(('应用名.urls', '应用名'), namespace='a'))
2.在app/urls.py文件中
from django.urls import path, re_path
from app.views import *
urlpatterns = [
path('index/', index),
# 访问index 跳转redirect_stu
path('redirect_stu/', redirect_stu, name='red'),
path('redirect_params/<int:id>/', redirect_params, name='rep'),
# 用正则时一定要在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'),
]
然后写相应的views,
3.views.py文件中写对应的urls的函数
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render
# HttpResponseRedirect实现跳转功能的
from django.urls import reverse
def index(request):
if request.method == 'GET':
# 跳转到另外一个路由地址上
# 无参的情况下进行跳转
# 第一种跳转: 使用硬编码url
# return HttpResponseRedirect('/app/redirect_stu/') # 不加/app 会报错, 没有写name时
# 第二种跳转: 使用反向解析 reverse('namespace:name')
# return HttpResponseRedirect(reverse('a:red')) # 反向解析'a:red'就是namespace:name
# 有参的情况下跳转
# 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':
# 跳转到另外一个路由地址上 在index.html中<a href="{% url 'a:red' %}">无参跳转
return HttpResponse('我是跳转方法')
def redirect_params(request, id):
if request.method == 'GET':
# 跳转到另外一个路由地址上,在index.html中{% url 'a:rep' 20 %}
return HttpResponse('带参的跳转, 参数: %s' % id)
def redirect_params_re(request, id):
if request.method == 'GET':
# 跳转到另外一个路由地址上,在index.html中{% url 'a:reb' 20 %}
return HttpResponse('带参的跳转2, 参数: %s' % id)
def req(request):
if request.method == 'GET':
return HttpResponse('请求')
def res(request):
if request.method == 'GET':
# 下面几个都是响应
# return HttpResponse('响应')
# return HttpResponseRedirect('跳转')
# return render()
# return JsonResponse({'code': 200})
response = HttpResponseRedirect('/app/index/')
response.set_cookie('token', 123456)
return response
2.另一个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自带的登录注册的实现
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实现登录注册注销功能
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':
# 获取数据并校验
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)
# 跳转
return HttpResponseRedirect(reverse('user:login'))
error = '用户已存在, 请更换账号'
return render(request, 'register.html', {'error': error})
else:
error = '注册参数有误, 请确认'
return render(request, 'register.html', {'error': error})
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
if request.method == 'POST':
# 获取数据
username = request.POST.get('username')
password = request.POST.get('password')
if username and password:
# 校验
user = auth.authenticate(username=username,
password=password)
if user:
# 设置登录状态
# 查看session是否变化, request.user这个东西的变化
# 变化: 开始是匿名用户, 运行这一步之后就显示你写的用户名了
auth.login(request, user)
# auth.logout(request)
return HttpResponseRedirect(reverse('user:index'))
error = '用户名或者密码错误'
return render(request, 'login.html', {'error': error})
else:
error = '登录信息请填写完整'
return render(request, 'login.html', {'error': error})
def index(request):
if request.method == 'GET':
# request上面绑定属性的, 如user属性, {{ user }}来调用
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':
# 获取数据并校验
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)
# 跳转
return HttpResponseRedirect(reverse('user:login'))
error = '用户已存在, 请更换账号'
return render(request, 'register.html', {'error': error})
else:
error = '注册参数有误, 请确认'
return render(request, 'register.html', {'error': error})
def my_login(request):
if request.method == 'GET':
return render(request, 'login.html')
if request.method == 'POST':
# 获取数据
username = request.POST.get('username')
password = request.POST.get('password')
if username and password:
# 校验
user = MyUser.objects.filter(username=username).first()
if user:
# 校验密码
if check_password(password, user.password):
# TODO 登录操作 m
request.session['user_id'] = user.id
return HttpResponseRedirect(reverse('user:index'))
error = '用户名或者密码错误'
return render(request, 'login.html', {'error': error})
else:
error = '登录信息请填写完整'
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(标识符)的字段 但客户端的数据还没删(删的是数据库的信息)
# del request.session['user_id']
# TODO 2.通过key来删掉整个数据退出 但客户端的数据还没删(删的是数据库的信息)
# request.session.delete(session_key)
# TODO 3.通过在客户端删除, 数据库也会删除数据
request.session.flush()
return HttpResponseRedirect('操作session数据')
3./user/models.py中 - 要用自己定义的登录注册先创建一个类
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'
网友评论