一、分组(回顾)
分组是存在于正则里面,就是因为路由文件里的url函数,这个函数第一个参数是支持正则的
1.无名分组:对一个正则表达式用小括号括起来
url('^index/\d+$', views.index)
url('^index/(\d+)$', views.index)
一旦给正则分组之后,会把正则匹配到的内容以位置参数的形式传递给视图函数
index视图函数应该有对应的形参来接收参数
def index(request, xx, yy, zz):
pass
2.有名分组
url('^index/(?P\d+)$', views.index)
一旦给正则分组之后,会把正则匹配到的内容以关键字参数的形式传递给视图函数
def index(request, year):
pass
二、反向解析(回顾)
反向解析的本质:给路由起一个名字,通过一些方法可以解析这个路由名字可以得到这个名字对应的路由地址
1.普通解析
1.先给路由起名字
url('^index/(?P\d+)$', views.index, name='index')
2.反向解析
url('^index/$', views.index, name='index')
3.后端反向解析:
from django.shortcuts import reverse
def index():
res=reverse('index')
print(res)
2.无名分组
1.反向解析
url('^index/(\d+)$', views.index, name='index')
2.后端反向解析:
from django.shortcuts import reverse
def index():
res=reverse('index', args=(123, ))
print(res)
3.有名分组的反向解析
url('^index/(?P\d+)$', views.index, name='index')
后端反向解析:
from django.shortcuts import reverse
def index():
res=reverse('index', kwargs={'year':123})
print(res)
前端反向解析
<a href='{% url 'index' 11 22 33 %}'></a>
<a href='{% url 'index' year=11 month=22 day=33 %}'></a>
三、路由的分发(回顾)
一个django项目只有一个总路由文件,随着项目的迭代,路由肯定会越来越多,路由多了就不容易维护了
所以我们对路由做了分发
总路由文件分发到各个应用里面,每个应用都应该有一个路由文件,默认是么有这个文件的,所以需要手动创建出来
问:如何操作?
在总路由文件里
1.第一种方式
url('^app01/', include(app01_urls))
url('^app02/', include(app01_urls))
2.第二种方式
url('^app01/', include('app01.urls'))
url('^app02/', include('app02.urls'))
3.注意事项:
路由的后缀不要加$
四、伪静态的概念(回顾)
把一个冬态的网页伪装成静态的页面
问:为什么要伪装成静态页面:
为了增加被搜索的可能性,seo
问:如何伪装成静态页面
url('^index.html/', include(app01_urls))
五、三板斧问题
1.注意:在视图函数中写函数跟普通函数不太一样
djagno中使用的局部的request
def index(request):
pass
def func(request):
pass
'''所有的视图函数不能够没有返回值,并且返回值还必须是HttpResponse对象'''
会报错:如果没有返回值 ----> The view app01.views.index didn't return an HttpResponse object. It returned None instead.
render()方法:
def render(request, template_name, context=None, content_type=None, status=None, using=None):
注意:其实我们的三板斧方法返回的都是HttpResponse对象
return HttpResponse('app01 index')
首先HttpResponse在源码中是一个类,在这里直接返回HttpResponse(),类加括号就是实例化,实例化就会调用__init__()方法,
2.在flask中request使用的是全局的request
from ... import request
def index():
pass
def func():
pass
问:所有的视图函数都使用全局的request对象,会不会乱套? 不会乱套,如何做到不乱套的? 在源码中揭晓.
六、JsonResponse序列化
1.json格式的数据?
主要就是实现跨语言数据传输
现在实现跨语言数据的传输使用的都是json,在以前使用的是xml
例如,微信支付朝微信的后端发送参数的时候,使用的就是xml
json格式的数据特点:
{"username":"kevin","age":18}
2.之前学的是如何序列化的?
import json
json.dumps -------------》 JSON.stringify()
json.loads -----------》JSON.parse()
d = {'username': 'kevin哈喽', 'age': 18}
import json
d_json = json.dumps(d, ensure_ascii=False)
return HttpResponse(d_json)
3.在js中是如何做的
JSON.stringify()
JSON.parse()
4.js中的对象
obj = new Object()
obj = {}
obj.username = 'kevin'
consolo.log(obj.username)
5.在Django中又该如何去序列化
from django.http import JsonResponse
d = {'username': 'kevin哈喽', 'age': 18}
return JsonResponse(d, json_dumps_params={'ensure_ascii': False})
l = [1, 2, 3, 4]
return JsonResponse(l, safe=False)
HttpResponse对象
1.HttpRequest.GET
一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象。
2.HttpRequest.POST
一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。
POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。
因此,不应该使用 if request.POST 来检查使用的是否是POST 方法;应该使用 if request.method == "POST"
另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。
注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用:
request.POST.getlist("hobby")
3.HttpRequest.body
一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。
但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。
4.HttpRequest.path
一个字符串,表示请求的路径组件(不含域名)。
例如:"/music/bands/the_beatles/"
5.HttpRequest.method
一个字符串,表示请求使用的HTTP 方法。必须使用大写。
例如:"GET"、"POST"
6.HttpRequest.encoding
一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。
这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。
接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。
如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。
7.HttpRequest.META
一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例:
取值:
CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
CONTENT_TYPE —— 请求的正文的MIME 类型。
HTTP_ACCEPT —— 响应可接收的Content-Type。
HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
HTTP_HOST —— 客服端发送的HTTP Host 头部。
HTTP_REFERER —— Referring 页面。
HTTP_USER_AGENT —— 客户端的user-agent 字符串。
QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
REMOTE_ADDR —— 客户端的IP 地址。
REMOTE_HOST —— 客户端的主机名。
REMOTE_USER —— 服务器认证后的用户。
REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。
SERVER_NAME —— 服务器的主机名。
SERVER_PORT —— 服务器的端口(是一个字符串)。
从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时,
都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_ 前缀。
所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。
8.HttpRequest.FILES
一个类似于字典的对象,包含所有的上传文件信息。
FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。
注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会
包含数据。否则,FILES 将为一个空的类似于字典的对象。
9.HttpRequest.COOKIES
一个标准的Python 字典,包含所有的cookie。键和值都为字符串。
10.HttpRequest.session
一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。
完整的细节参见会话的文档。
11.HttpRequest.user(用户认证组件下使用)
一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。
如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们。
例如:
if request.user.is_authenticated():
else:
user 只有当Django 启用 AuthenticationMiddleware 中间件时才可用。
-------------------------------------------------------------------------------------
匿名用户
class models.AnonymousUser
django.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口,但具有下面几个不同点:
id 永远为None。
username 永远为空字符串。
get_username() 永远返回空字符串。
is_staff 和 is_superuser 永远为False。
is_active 永远为 False。
groups 和 user_permissions 永远为空。
is_anonymous() 返回True 而不是False。
is_authenticated() 返回False 而不是True。
set_password()、check_password()、save() 和delete() 引发 NotImplementedError。
New in Django 1.8:
新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。
七、 form表单上传文件
注意:form表单上传文件的前提:
1. 请求方式必须是post
2. enctype必须是form-data
<form action="" method="post" enctype="multipart/form-data">
<input type="text" name="username">
上传文件:<input type="file" value="上传文件" name="myfile">
<input type="submit" value="提交">
</form>
def ab_file(request):
print(request.POST)
print(request.FILES)
if request.method == 'POST':
file_obj = request.FILES.get('myfile')
with open(file_obj.name, 'wb') as f:
for line in file_obj:
f.write(line)
return render(request, 'ab_file.html')
八、request对象的其他几个方法
request.GET
request.POST
request.FILES
request.path_info
reqeust.path
request.get_full_path()
request.body
1.HttpRequest.get_full_path()
返回 path,如果可以将加上查询字符串。
例如:"/music/bands/the_beatles/?print=true"
注意和path的区别:http://127.0.0.1:8001/order/?name=lqz&age=10
2.HttpRequest.is_ajax()
如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串'XMLHttpRequest'。
大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。
如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware,
你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应能够正确地缓存。
render()
render(request, template_name[, context])` `结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。
参数:
request: 用于生成响应的请求对象。
template_name:要使用的模板的完整名称,可选的参数
context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。
render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。
九、C(class)BV的书写和F(function)BV的写法
目前写的都是FBV:function based view 基于函数的视图
在视图文件中书写类 CBV:class based view 基于类的视图
postman的官网地址:https://www.postman.com/downloads/
apizza的挂网地址:http://www.apizza.net/
所有的类必须继承django的view类
from django.views import View
class MyLogin(View):
类里面的方法名字不能够随便写,目前只能写get post等
访问这个地址必须是get请求方式
def get(self, request):
print("get")
return HttpResponse("get")
访问这个方法必须是psot请求方式
通过form表单发送post请求
出了form表单,我们还可以使用工具来模拟
def post(self,request):
print("post")
return HttpResponse("post")
十、CBV的源码分析
看过Django的哪些源码,简单说说?
CBV的源码、settings的源码、权限、频率、认证的、签发token的源码
看源码的步骤是先找到源码的入口
CBV的入口在哪里呢?
path('login/', views.MyLogin.as_view()),
views.MyLogin.as_view()
"""
类名可以调用哪些方法:
1. 方法被@classmethod装饰器修饰的方法
类名来调用类方法有什么特殊之处:
会把类名自动当成第一个参数传递给方法的第一个形参cls
对象调用方法把对象自己当成第一个参数传给方法的第一个形参self
2. 被@staticmethod装饰器修饰的方法
"""
@classonlymethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.setup(request, *args, **kwargs)
if not hasattr(self, 'request'):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
return self.dispatch(request, *args, **kwargs)
return view
path('login/', View.view),
当请求来的时候,开始匹配路由login,就会调用View.view()
def view(request, *args, **kwargs):
self = cls(**initkwargs)
"""
self: MyLogin()
"""
return self.dispatch(request, *args, **kwargs)
第七步:
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
问题:如何让我写的CBV类只支持get请求或者只支持post请求?
源码是用来看的,不是用来改的,有时候也能够改,但是你不行,你这个阶段先不要想着改人家源码的
class MyLogin(View):
http_method_names = ['get',]
def get(self, request):
print("get")
return HttpResponse("get")
十一、模板变量之分配
{{ }} 一般写变量
{% %} 一般写逻辑
def func(request):
d = {'username': 'jack', 'hobby': ['read', 'music', 'dance']}
a = 1
b = 1.11
c = 'helloworld'
e = True
f = [1, 2, 3, 4]
g = (1, 2, 3, 4)
h = {1, 2, 3, 4}
def index():
return 'index'
class Login():
def index(self):
return 'login.index'
return render(request, 'func.html', context=locals())
前端页面:
{{ d }}
{{ a }}
{{ b }}
{{ c }}
{{ e }}
{{ f }}
{{ g }}
{{ h }}
{{ index }}
{{ Login.index }}
模板中取值一定使用的是句点符.
模板中的函数一定不能够加括号,他们会自动帮你加括号调用
{{ f.1 }}
{{ f.2 }}
{{ f.3 }}
{{ d.hobby.1 }}
十二、模板之过滤器
Django自带的过滤器有好几十、但是我们没必要全部记住,只需要记住几个就行了
语法:
{{ obj|过滤器名称:参数 }} 变量名字|过滤器名称:变量
案例:
若是False就打印 你很好啊
{{ res|default:'你很好啊' }}
长度
{{ res|length }}
文件尺寸的大小
{{ res|filesizeformat }}
日期
{{ res|date:'Y-m-d' }}
截取字符串
{{ res|truncatechars:9 }}
获取标签使用
{{ res|safe }}
{{ res }}
二进制的位移