Django-3
目录
Django-3
JsonResponse
返回json格式的数据
为什么要给前端返回json格式的字符串
前后端分离,就是基于json格式传输数据
前端从后端写的接口中拿到一个能够共同识别的json格式的数据
前端 | 后端 |
---|---|
JSON.stringify() | json.dumps() |
JSON.parse() | json.loads() |
# JsonResponse,后端给前端传json数据
def index(request):
dic = {'username':'jason真帅 我好喜欢哦~','pwd':'123'}
#### 指定json序列化时,不自动转ascii,这样就能显示中文了
json_str = json.dumps(dic,ensure_ascii=False)
return HttpResponse(json_str)
#### 利用JsonResponse里的json_dumps_params的默认值,改为字典{'ensure_ascii':False}的键值对形式,也能将中文显示出来。
return JsonResponse(dic,json_dumps_params={'ensure_ascii':False})
lis = [1,2,3,4,5,]
str = 'aiefiaef'
b = True
#### JsonResponse默认只支持序列化字典 如果你想序列化其他类型(json能够支持的类型) 你需要将safe参数由默认的True改成False
return JsonResponse(b,safe=False)
form表单上传文件
注意事项:
- 提交方式必须是post
enctype
参数必须重置为multipart/form-data
# up.html
<form action="" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username">
<input type="file" name="myfile" >
<input type="submit" class="btn btn-danger">
</form>
# 表单上传文件
def up(request):
if request.method == 'POST':
print(request.POST)
print(request.FILES)
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,'up.html')
CBV源码分析
-
**FBV **(Function Based View) 基于函数的视图
-
CBV (Class Based View) 基于类的视图
案例:
1 配置路由
url(r'^reg/',views.get_post.as_view()),
2 编写视图类
from django.views import View
class get_post(View):
def get(self,request):
return render(request,'reg.html')
def post(self,request):
return HttpResponse('jason牛逼')
'''
当前端发送get请求时,会响应get方法,返回reg.html
当前端发送post请求时,会响应post方法,返回相应的字符串
为什么会这样呢???
'''
3 编写html页面
# reg.html
# 当只访问reg.html页面时,发送的是get请求,当提交表单数据时,发送的是post请求
<form action="" method="post">
<h1> get 页面 </h1>
<input type="submit" class="btn btn-danger">
</form>
分析
@classonlymethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs) # cls就是我们自己的写的MyReg类
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
# 上面的一通操作 就是给我们自己写的类的对象赋值
return self.dispatch(request, *args, **kwargs)
return view
"""CBV最精髓的部分"""
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)
'''
首先,as_view是View的一个类方法,当类来调用是,自动将类当作第一个参数传给as_view
as_view内部的view函数先是自定义了类本身的名称空间,并且将携带所有的参数交给dispatch方法
然后在dispatch中,拿到self(也就是自定义类实例化得到的对象)和参数,
先判断小写的请求方式在不在已经定义好的八大请求这个列表中
如果在的话,通过小写的请求方式字符串反射拿到对应请求方式的对象handler,其实handler就是自定义类中自定义的方法,如get或者post
如果不在的话,将报错信息的内存地址赋值给handler
最后调用handler这个对象,并且将结果返回。
'''
模板传值
基本上前端能够接收所有后端能传过来的数据类型,包括函数对象或者类实例化的对象
但也有一些不好的地方,例如:
- 传函数名的时候,会自动加括号调用函数,将函数的返回值展示在html页面上
- django模板语法不支持函数传值
- django模板语法在获取容器类型内部元素的值的时候,统一只采用句点符(.),不支持中括号取值和.get()取值。这一点jinja2模块做的更好。
过滤器
常见的过滤器:
|add:
|length:
|truncatechars:
|truncatewords:
|date:
|safe
|default:
<p>{{ num|add:100 }}</p>
<p>{{ str|add:'菜鸡' }}</p>
<p>{{ lis|length }}</p>
<hr>
<p>{{ chuan|truncatechars:15 }}</p>
<p>{{ chuan1|truncatechars:15 }}</p>
<hr>
<p>{{ dtime|date:'y年-m月-d日' }}</p>
<hr>
<p>{{ sss|safe }}</p> 在后端用字符串写前端代码传给前端,用safe过滤器才会在前端起效果
也可以在后端指定用mark_safe()方法,效果等同于safe过滤器。
标签
- if判断
- for循环
{% for f in lis %}
{% if forloop.first %}
<p>第一次循环到我</p>
{% elif forloop.last %}
<p>最后一次循环</p>
{% else %}
<p>循环体</p>
{% endif %}
{% endfor %}
# forloop对象
{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}
自定义过滤器和标签
步骤
- 在应用名下新建一个templatetags文件夹
- 在该文件夹下新建一个任意名字的py文件
- 在该文件中导入Library模块
- 实例化一个Library对象,并且固定叫register
自定义过滤器:
from django.template import Library
register = Library()
# 所传的两个参数如果是字母则相加并大写,否则返回空字符
@register.filter(name='myupper')
def ss(a,b):
if a.isalpha() and b.isalpha():
return (a+b).upper()
return ''
# 使用
{% load my_tag %}
<p>{{ 'faef'| myupper:'afhiawf' }}</p>
自定义标签:
from django.template import Library
register = Library()
# 将所传参数里的数字相加
@register.simple_tag(name='myadd')
def xx(*args):
l = len(args)
s = 0
for i in range(l):
if isinstance(args[i],int):
s += args[i]
return s
# 使用
{% load my_tag %}
{% myadd 1 4 5 6 %}
模板的继承
事先需要在模板中 通过block划定区域
{% block 区域名字 %}
{% endblock %}
子板中如何使用
{% extends '模板的名字'%}
{% block 区域名字 %}
<h1>登录页面</h1>
{% endblock %}
一个页面上 block块越多 页面的扩展性越高
通常情况下 都应该有三片区域
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
子板中还可以通过{{ block.super }} 来继续使用母版的内容
模板的导入
当你写了一个特别好看的form表单,你想再多个页面上都使用这个form表单,你就可以将你写的form表单当作模块的形式导入,导入过来之后,就可以直接展示。
{% include 'good_page.html' %}