一、Views
views模块为MVC中的C——Controller,逻辑处理,是连接MTV中model(数据库数据)与Template(视图模块)的结合,将数据库中的数据显示到视图中
视图的本质就是一个python中的函数
Django中,视图主要用来接受Web请求,并做出响应
视图的响应分为两种:
- 以JSON数据形式返回
- 以网页的形式返回(重定向到另一个页面、错误视图40X,50X)
视图响应的过程:浏览器输入——>django获取信息并去掉IP:端口号,剩下路径——>urls路由匹配——>视图响应——>回馈到浏览器
Views 视图函数
- MTV中的View,相当于Controller作用,控制器 接收用户输入(请求),协调模版模型,对数据进行处理
- 路由器urls
- urlpatterns
- 根路由url中,我们会使用include形式将整个子路由添加进来
- 第一个参数:正则匹配的路径
- 第二个参数:包含那个路由
- 第三个参数:namespace
- 子路由中,前两个参数一致
- 第三个参数:name
- 以后我们会根据namespace:name 动态获取我们的路由(path)
- 请求参数
- 路径参数
- 位置参数
- 使用圆括号包含规则
- 一个圆括号代表一个参数
- 代表视图函数上的一个参数
- 参数个数和视图函数上的参数一一对应(除默认request)
- 关键字参数
- 可以在圆括号指定参数名字 (?P<name> reg)
- 视图函数中存在和圆括号中name对应的参数
- 参数不区分顺序
- 个数也需要保持一致,一一对应
- 位置参数
- 请求参数
- 反向解析
- 在模版中使用
- {% url %}
- {% url 'namespace:name' %}
- 如果存在位置参数:{% url 'namespace:name' value1 value2 ... %}
- 如果存在关键字参数:{% url 'namespace:name' key1=value1 key2=value2 ... %}
- 规则
- 按照书写顺序,从上到下匹配
- 没有最优匹配的原则,匹配到就停止
- 路径参数
- 双R
- Request
- django框架根据Http请求报文自动生成的一个对象
- 包含请求各种信息
- path、method(GET、POST请求)、encoding、GET(QueryDict、类字典结构key-value,一个key可以对应多个值、get、getlist)、POST、FILES、COOKIES、session、is_ajax()
- META:元信息 包括:客户端id的所有信息、IP地址等
- Response
- Request
二、Urls
路由
- 按照列表的书写顺序进行匹配,从上到下匹配,没有最优匹配的概念
- 路由规则编写:通常直接指定'xxx',在结尾添加反斜线 /,path(‘xxx/', views.xxx)
URL组成:http | ://www.xxx.com | /xx/index/ | ?u_token=xxx&u_time=14.37 | #footer
- http:schema协议 常见有http、https、ftp传文件、rtmp直播流
- www.xxx.com:域名 ip:port http没有书写端口则默认是80端口
- /xxx/index/:路径path 相当于主机的绝对路径
- ?u_token=xxx&u_time=14.37:GET请求参数(QueryString 查询参数)
- #footer:锚点,页面中的定位方式
路由规则编写
- 通常直接指定path("路由路径", views.xxx) views中新建方法并逻辑编写
- 在结尾处直接添加反斜线 \
路由路径中参数使用()进行获取
- 一个圆括号对应视图函数中的一个参数
- 参数:
- 路径参数
- 位置参数:按照书写顺序进行匹配
- 关键字参数:(?P<参数名称>\d+) 按照参数名称匹配,和顺序无关
- 参数个数必须和视图函数中参数个数一致(除默认的request以外)
- 路径参数
- 例如:
from django.urls import path,re_path urlpatterns = [ # path('students/', views.students), #'^xxx/(?P<id>\d+)/' 路由:/xxx/一位或多位数字 # re_path('^student/(?P<id>\d+)/', views.student), re_path('students/$', views.students), re_path('students/(\d+)/', views.student), re_path('time/(\d+)/(\d+)/(\d+)/', views.get_time, name='get_time'), re_path('date/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)/', views.get_date, name='get_date'), ]
url反向解析
- 根据根路径中注册的namespace和在子路由中注册name,这两个参数来动态获取我们的路径
- 在模版中使用 {% url 'namespace:name' %}
- 如果带有位置参数{% url 'namespace:name' value1 value2 [valuen...] %}
- 如果带有关键字参数{% url 'namespace:name' key1=value1 key2=value2 [keyn=valuen...] %}
- 根据路径中注册的标识动态获取路径
- 反向解析优点:
- 如果在视图模板中使用硬编码连接,在url配置发生改变时,需要变更的代码会非常多,这样导致我们的代码结构不是很容易维护,使用反向解析可以提高我们代码的扩展性和可维护性。
- 例如:
项目urls.py from django.contrib import admin from django.urls import path, include path('two/', include(('TwoApp.urls', 'second'), namespace='second')), 或 path('two/', include(('TwoApp.urls'), namespace='second')), 应用TwoApp urls.py from django.urls import path, include from TwoApp import views urlpatterns = [ path('learn/', views.learn, name='learn'), ] .html 中调用 <a href="{% url 'second:learn' %}">button</a> second:项目中定义的命名空间namespace名称,由命名空间名称找到路由two/ learn:应用中定义的name名称,由name名称找到路由learn/ 当更改项目中的path('two/', ...) 为 path('more/', ...)时,路由反向解析为 ip:port/more/learn/
POST反向解析:
-
项目 urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('one/', include(('oneapp.urls', 'first'), namespace='first')), ] 应用APP urls.py from django.urls import path, include from oneapp import views urlpatterns = [ path('have/', views.have_request), path('create_student/', views.do_create_student, name='do_create_student'), ] 应用APP views.py def have_request(request): return render(request, 'student.html') def do_create_student(request): username = request.POST.get('username') return HttpResponse(username) 页面 student.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Student</title> </head> <body> <!--表单输入--> <form action="{% url 'first:do_create_student' %}" method="post"> <span>UserName:</span><input type="text" name="username" placeholder="please input username"> <button>Submit</button> </form> </body> </html>
Django使用时,2.0版更新后不能使用之前 include namespace 的方式书写
在网页项目中使用include()方法
项目目录中同时存在app/urls.py和proj/urls.py
在proj/urls.py使用include方法
from django.urls import path, include
from app import urls as app_url
urlpatterns = [
path('xxx/', include(app_url, namespace='common')),
]
在app/urls.py中对应url
from django.urls import path
from.views import index
urlpatterns = [
path('路由名称', views.方法名, name='index'),
]
runserver发生错误
django.core.exceptions.ImproperlyConfigured:
Specifying a namespace in include() without providing an app_name is not supported.
Set the app_name attribute in the included module,
or pass a 2-tuple containing the list of patterns and app_name instead.
意思为:
在include方法里面指定namespace却不提供app_name是不允许的。
在包含的模块里设置app_name变量,或者在include方法里面提供app_name参数。
解决方法:
在项目的urls.py文件中,即 proj/urls.py中修改
from django.urls import path,include
from app import urls as app_url
urlpatterns = [
path('xxx/', include((common_url,'common'), namespace='common')),
]
例如: path('two/', include(('TwoApp.urls', 'second'), namespace='second')),
方法2:在应用 app/urls.py中修改
from django.urls import path
from .views import index
app_name='common'
urlpatterns = [
path('xxx/',index,name='index'),
]
使用方式:
在页面html5文件中使用反向代理:
<a href="{% url 'second:learn' %}">Go Go Go</a> #second 为project urls中的namespace learn为App中的name
错误页面定制
- 在模版中重写对应错误状态码页面,例如新建404.html页面
- 关闭Debug
- 实现原则
- 接近原则
- 例:在templates中,新建404.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>404</title> <head> <body> <h3>Client Request is Not Found</h3> </body> </html>
双R
Request
Django框架会进行自己的包装,之后传递给视图
- 属性
- path 请求的完整路径
- method 请求的方法,常用GET、POST
- encoding 编码方式,常用utf-8
- GET 类似字典的参数,包含了get的所有参数
- 类字典结构
- 一个key允许对应多个值
- get、getlist
- POST 类似字典的参数,包含了post所有参数
- FILES 类似字典的参数,包含了上传的文件
- COOKIES 字典,包含了所有COOKIE
- session 类似字典,表示会话
- 方法:is_ajax()
- 判断是否是ajax()
- 通常用在移动端和JS中
- META
- 各种客户端元信息
- REMOTE_ADDR远端访问IP
Resonse
- 属性
- content 返回的内容
- charset 编码格式
- status_code 响应状态码(200,3xx,404,5xx)
- content-type MIME类型
- MIME作用:指定传输数据使用哪种形式打开
- 格式:大类型/小类型 如:image/png image/jpg
- Json
- JsonObject
- { }
- key - value
- JsonArray
- [ ]
- 列表中可以是普通数据类型,也可以是JsonObject
- JsonObject和JsonArray可以嵌套
- 给移动端的json
- 给Ajax
- 前后端
- DRF
- Google Chrome谷歌浏览器
- jsonFomatter
- jsonView
- JsonObject
- 方法
- init 初始化内容
- write(xxx) 直接写入文本
- flush() 冲刷缓冲区
- set_cookie(key, value='xxx',max_age=None,exprise=None) 设置cookie
- delete_cookie(key) 删除cookie
- HttpResponse
- HttpResponseRedirect
- from django.urls import reverse def xxx(request): url = reverse('namespace:name') return HttpResponseRedirect(url)
- 重定向,暂时 302
- 简写:redirect
- JsonResponse
- 以json格式返回数据
- 重写了_init_,序列化Json数据,指定content-type为application/json
- HttpResponsePermanentRedirect
- 重定向,永久 301
- HttpResponseBadRequest
- 400
- HttpResponseNotFound
- 404
- HttpResponseForbidden
- 403
- HttpResponseNotAllow
- 405
- HttpResponseServerError
- 500
- Http404
- Exception
- raise 主动抛出异常
- HttpResponseRedirect
会话技术
请求后给客户端发送令牌,下次再请求时拿着令牌,服务器就会自动识别客户端
- 出现场景
- 服务器如何识别客户端
- Http在Web开发中基本都是短连接
- 请求生命周期
- 从Request开始
- 到Response结束
- Cookie
- 客户端会话技术
- 数据存储在客户端
- 键值对存储
- 支持过期时间 7*24*60*60 7天失效,如果清理缓存,则立马失效
- 默认Cookie会自动携带本网站所有Cookie
- Cookie跨域名,跨网站
- 通过HttpResponse操作客户端
- 设置Cookie response.set_cookie(key, value, max_age=None, exprise=None)
- max_age:整数,指定cookie过期时间
- expires:整数,指定过期时间,还支持datetime或timedelta,可以指定一个具体日期时间
- max_age和expries两个选一个指定
- 过期时间的几个关键时间
- max_age设置为0, 浏览器关闭失效,设置为None,永不过期
- expires=timedelta(days=10) 10天后过期
- Cookie默认不支持中文(添加中文是使用base64加密技术)
- Cookie 加盐 salt response.set_signed_cookie(key, value, salt='', **kwargs)
- 加密
- 获取时需要解密 request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
- Cookie 删除 response.delete_cookie('key')
- 客户端会话技术
- Session
- 服务端会话技术
- 数据存储在服务器中
- 默认Session存储在内存中
- Django中默认会把Session持久化到数据库中
- Django中Session的默认过期时间是14天
- 主键是字符串
- 数据使用数据安全
- 使用base64加密
- 在前部添加了混淆
- Session 设置 request.session['key'] = value
- Session 获取 request.session.get('key')
- Session 删除 request.session.flush() session、cookie一起删除
- 服务器端会话技术依赖于Cookie
- django中启用SESSION
- settings中 INSTALLED_APPS: 'django.contrib.sessions' MIDDLEWARE:'django.contrib.sessions.middleware.SessionMiddleware'
- 每个HttpRequest对象都有一个session属性,也是一个类字典对象
- Token
- 服务端会话技术
- 自定义的Session
- 缺陷:session依赖于cookie cookie依赖于浏览器
- 如果使用Web页面开发,使用起来和Session基本一致
- 如果使用移动端或客户端开发中,通常一Json形式传输,需要移动端自己存储Token,需要获取Token关联数据的时候,主动传递Token
- Cookie、Session、Token对比
- Cookie使用更简洁,服务器压力更小,数据不是很安全
- Session服务器要维护Session,相对安全
- Token拥有Session的所有优点,自己维护略微麻烦,支持更多的终端
CSRF
- 防跨站攻击
- 防止恶意注册,确保客户端是我们自己的客户端
- 使用了cookie中csrftoken进行验证、传输
- 服务器发送给客户端,客户端将cookie获取过来,还要进行编码转换(数据安全)
- 如何实现
- 在我们存在csrf_token标签的页面中,响应会自动设置一个cookie、csrftoken
- 当我们提交的时候,会自动验证csrfttoken
- 验证通过,正常执行以后流程,验证不通过,直接403
知识点
locals
- 内置函数
- 将局部变量使用字典的方式进行打包
- key是变量名,value是变量中存储的数据
登录
- 首先有一个页面
- 页面中有输入框
- 有登录按钮
- 点击登录按钮,默认进入个人中心
- 个人中心可以显示用户名