request对象的几个方法
1.request.path:获取url地址的路径部分,只包含路径部分
2.request.path_info
3.request.get_full_path() 获取url地址的完整path,既包含路径又包含参数部分
4.request.body 浏览器发过来的二进制数据
def index(request,a):
print('hello')
print(request.path) # /index/
print(request.path_info) # /index/
print(request.get_full_path()) # /index/ /index/?username=kevin
print(request.body) # b''
return render(request,'index.html')
CBV和FBV
1.CBV:class based views:在视图中写类
2.FBV:function based views:在视图中写函数
3.怎样在视图中写类:
1.urls.py:url(r'正则',类名.as_view())
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^MyLogin/', views.MyLogin.as_view())]
2.views.py:导模块--类必须继承View---有get、post函数(分别代表get请求,post请求)
from django.views import View
class MyLogin(View):
def get(self,request): # 通过get请求方式会访问到这个方法
return HttpResponse('get请求')
def post(self,request): # 通过post请求方式会访问到这个方法
return HttpResponse('post请求')
4.第三方工具:postman(在官网下载)、apizz(网页版,不需要下载,注册登陆即可)
CBV源码剖析
1.看源码:首先先找入口---CBV入口:路由 as_view()
2.views.MyLogin.as_view()---分析:类调用方法
1.类来调用方法:
1. 被@classmethod装饰器修饰的方法
2. 被@staticmethod装饰器修饰的方法
我们在MyLogin类中并没有写as_view(), 可能会在父类中
3.鼠标+contrl点进去:
@classonlymethod
def as_view(cls, **initkwargs):
for key in initkwargs:
pass
def view(request, *args, **kwargs):
self = cls(**initkwargs) # self = MyLogin()
return self.dispatch(request, *args, **kwargs)
return view
4.推论:
1.
views.MyLogin.as_view()--->View类里面的as_view方法中得view方法的内存地址
views.MyLogin.as_view()--->本质也是函数的内存地址
2.当请求来了,会自定触发view函数的执行---->会触发view()函数
分析view返回值--self.dispatch(request, *args, **kwargs)
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names:
# self.http_method_names-->对象自己查找-类里查找--父类里查找(http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'])
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
分析返回值:handler(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) # getattr():获取对象字符串对应得属性(handler =getattr(self, 'get'))----->get函数的内存地址
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
需求:我写的这个类只允许get请求,怎么做?
class MyLogin(View):
http_method_names = ['get', 'post']
def get(self, request):
return HttpResponse('get')
def post(self, request):
return HttpResponse('post')
模版层
简单来说,模版层就是html文件,在html文件里面django给你提供了一些模版语法,是html自身不自带的
模版的变量分配
1.模版里面的取值一律使用点语法(eg:列表取值)
2.{{ }} 变量相关
{% %} 逻辑相关
3.在模版语法里,函数的使用不需要加括号,直接使用函数名,会自动调用 ps:不能传参
例子
1.
def foo(request):
dic1 = {'name':'123','gender':'female'}
a = {'b':1}
# return render(request,'foo.html',context={'userdic':dic1,'aa':a})
return render(request,'foo.html',locals())
2.
# foo.html
{{ a }}
{{ b }}
{{ c }}
{{ d }}
{{ d.0 }}
{{ e }}
{{ e.name }}
{{ f }}
{{ g }}
{{ h }}
# views.py
def foo(request):
a = 1
b = 1.2
c = True
d = [1,2,3,4]
e = {'name':'123','gender':'female'}
f ={1,2,3,4}
g = 'hello world'
h = (1,2,3,4)
return render(request,'foo.html',locals())
# 浏览器
1 1.2 True [1, 2, 3, 4] 1 {'name': '123', 'gender': 'female'} 123 {1, 2, 3, 4} hello world (1, 2, 3, 4)
3.函数:函数的时候,不需要加括号,直接使用函数名,它会自动给你加括号调用--不可传参
# foo.html
{{ func }}
# views.py
def func():
return 'func'
return render(request,'foo.html',locals())
# 浏览器
func
模版之过滤器
1.django提供的过滤器:filter__name
2.语法:
{{obj|filter__name:param}} 变量名字|过滤器名称:变量
常用过滤器
1.default:默认值
作用:如果一个变量值是False或者为空、None,使用default后指定的默认值,否则,使用变量本身的值,如果value=’‘则输出“nothing”
{{ value|default:"nothing" }}
2.default_if_none
作用:如果只针对value是None这一种情况来设置默认值,需要使用default_if_none
只有在value=None的情况下,才会输出“None...”,
{{ value|default_if_none:"None..." }}
3.length:长度
作用:返回值的长度。它对字符串、列表、字典等容器类型都起作用,如果value是 ['a', 'b', 'c', 'd'],那么输出是4
{{ value|length }}
4.filesizeformat:转换人类可读的文件大小
作用:将值的格式化为一个"人类可读的"文件尺寸(如13KB、4.1 MB、102bytes等等),如果 value 是 12312312321,输出将会是 11.5 GB
{{ value|filesizeformat }}
5.date:格式化日期(时间戳不可)
作用:将日期按照指定的格式输出,如果value=datetime.datetime.now(),按照格式Y-m-d则输出2019-02-02
{{ value|date:"Y-m-d" }}
7.slice:切字符串
作用:对输出的字符串进行切片操作,顾头不顾尾,如果value=“egon“,则输出"eg"
{{ value|slice:"0:2" }}
8.truncatechars:截取
作用:如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾,如果value=”hello world egon 嘎嘎“,则输出"hello...",注意8个字符也包含末尾的3个点
{{ value|truncatechars:8 }}
9.truncatewords
作用:同truncatechars,但truncatewords是按照单词截断,注意末尾的3个点不算作单词,如果value=”hello world egon 嘎嘎“,则输出"hello world ..."
{{ value|truncatewords:2 }}
10.safe:渲染标签--xss攻击、sql注入 csrf 密码加盐(安全相关)
1.
s1 = '<h1>hello</h1>'
{{ s1|safe }}
2.
后端:导模块 from django.utils.safestring import mark_safe
from django.utils.safestring import mark_safe
s1 = mark_safe('<h1>hello</h1>')
模版之标签
for循环
1.快捷键:for+tab--自动不全
{% for foo in l1 %}
{% endfor %}
2.基本使用
{% for foo in l1 %}
<p>{{ foo }}</p>
{% endfor %}
forloop
1.
{% for foo in l1 %}
<p>{{ forloop }}</p>
{% endfor %}
>>>{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 7, 'revcounter0': 6, 'first': True, 'last': False}
2.counter0:索引;counter:计数;first:第一个值; last:最后一个值
1.forloop.counter:当前循环的索引值(从1开始)
2.forloop.counter0:当前循环的索引值(从0开始)
3.forloop.revcounter:当前循环的倒序索引值(从1开始)
4.forloop.revcounter0:当前循环的倒序索引值(从0开始)
5.forloop.first:当前循环是不是第一次循环(布尔值)
6.forloop.last:当前循环是不是最后一次循环(布尔值)
7.forloop.parentloop:本层循环的外层循环
遍历字典
# views.py
def fun(request):
# l1 = [1,2,3,4,5,6,7]
dic = {'name':'nana','kwd':123,'gender':'female'}
return render(request,'fun.html',locals())
# fun.html
{% for foo in dic.values %}
{{ foo }}
{% endfor %}
{% for foo1 in dic.items %}
{{ foo1 }}
{% endfor %}
{% for foo2 in dic.keys %}
{{ foo2 }}
{% endfor %}
# 浏览器
nana 123 female ('name', 'nana') ('kwd', 123) ('gender', 'female') name kwd gender
for...empty --为空执行
1.for标签可以带有一个可选的{% empty %} 从句,在变量person_list为空或者没有被找到时,则执行empty子句
2.
{% for person in person_list %}
<p>{{ person.name }}</p>
{% empty %}
<p>sorry,no person here</p>
{% endfor %}
了解:Django框架的for循环,没有break和continue方法,可以使用自定义过滤器实现forloop | continue和forloop | break,参考:djangosnippets.org/snippets/20…
if标签
1.{% if 条件 %}条件为真时if的子句才会生效,条件也可以是一个变量,if会对变量进行求值,在变量值为空、或者视图没有为其传值的情况下均为False
2.具体语法
{% if num > 100 or num < 0 %}
<p>无效</p>
{% elif num > 80 and num < 100 %}
<p>优秀</p>
{% else %}
<p>凑活吧</p>
{% endif %}
3.if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
with--起别名
1.ith标签用来为一个复杂的变量名起别名,如果变量的值来自于数据库,在起别名后只需要使用别名即可,无需每次都向数据库发送请求来重新获取变量的值
2.
l1 = [1,2,3,4,4,[1,2,3,{'name':'nana'}]]
{% endif %}
{% with l1.5.3.name as v %}
{{ v }}
{% endwith %}
csrf_token标签
1..当用form表单提交POST请求时必须加上标签{% csrf_token %},该标签用于防止跨站伪造请求--就可以配置文件:一行的csrf不注释
<form action="" method="POST">
{% csrf_token %}
<p>用户名:<input type="text" name="name"></p>
<p>密码:<input type="password" name="pwd"></p>
<p><input type="submit" value="提交"></p>
</form>
2.具体工作原理为:
1、在GET请求到form表单时,标签{% csrf_token%}会被渲染成一个隐藏的input标签,该标签包含了由服务端生成的一串随机字符串,如<input type="hidden" name="csrfmiddlewaretoken" value="dmje28mFo...OvnZ5">
2、在使用form表单提交POST请求时,会提交上述随机字符串,服务端在接收到该POST请求时会对比该随机字符串,对比成功则处理该POST请求,否则拒绝,以此来确定客户端的身份
模版的继承和导入
模版的继承
需求:模仿x-admin做一个后台管理页面
1.{% extends 'home.html' %} ---继承home的页面
2.改部分页面内容---在home页面标记
{% block content %} ----contend 只是命的名字
....
{% endblock %}
3.在其他页面改被标记的内容
{% block content %}
....
{% endblock %}
4. 一个模板页面中应该至少有3块内容可以被替换
1. css
2. js
3. html
4.1 在模版页面head标签内写
{% block css %}
<style>
</style>
{% endblock %}
4.2 在模版页面body标签内写
{% block js %}
<script>
</script>
{% endblock %}
4.3 在需要修改的页面里写
{% block css %}
<style>
...
</style>
{% endblock %}
{% block js %}
<script>
...
</script>
{% endblock %}
模版的导入
1.{% include 'welcom.html' %}------>想要导入的页面写