Django框架入门教程:网站伪静态、视图层和模板层
网站伪静态
将动态网页伪装成静态网页,可以提升网页被搜索引擎检索道德概率
表现形式为:网址看着像是一个具体的文件路径例如:http://127.0.0.1:8001/admin/login/
path('index.html', views.index)
视图层
1.视图函数♓♸视图函数在views.py中没有定义可以看到,在设置返回值的时候,django报了如下错误:
报错信息:The view app01.views.home didn't return an HttpResponse object. It returned None instead. 视图app01.views.home没有返回HttpResponse对象。它返回None。
由此我们可以得出结论: 视图函数必须返回一个HttpResponse对象 当我们ctrl+左键点击进入HttpResponse时,我们发现它是一个类:
class HttpResponse(HttpResponseBase):
pass
但是视图函数还可以返回render并重定向对象。我们进入这两个函数来了解一下:
def render(...):
pass
return HttpResponse(content, content_type, status)
render函数的返回值也是一个HttpResponse对象。我们再看一下重定向:
def redirect(to, *args, permanent=False, **kwargs):
redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
return redirect_class(resolve_url(to, *args, **kwargs))
重定向函数的返回值也是一个HttpResponse对象。
可以看出,视图函数views.py必须返回一个HttpResponse对象
2。 view函数返回json格式的数据。只需要一行代码就替代了上面方法中的三行代码,非常好用。但有一个问题。 JsonResponse没有secure_ascii参数,这意味着我们暂时无法阻止汉字编码。为了解决这个问题,我们首先查看JsonResponse的源码: class JsonResponse(HttpResponse):
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
if json_dumps_params is None:
json_dumps_params = {}
kwargs.setdefault('content_type', 'application/json')
data = json.dumps(data, cls=encoder, **json_dumps_params)
super().__init__(content=data, **kwargs)
class JsonResponse(HttpResponse):
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
if json_dumps_params is None:
json_dumps_params = {}
kwargs.setdefault('content_type', 'application/json')
data = json.dumps(data, cls=encoder, **json_dumps_params)
super().__init__(content=data, **kwargs)
可以看到JsonResponse中有一个json.dumps方法,但是这个方法必须传递一些特殊的参数:**json_dumps_params。该参数用于接收冗余关键字参数,并将k:v拆分为键值对。这些关键字必须作为字典作为 json_dumps_params 的值传递。所以:
JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False})
这个和设置**'ensure_ascii':False**是一样的,不过设置这个参数有点坑~~
除了字典类型,其他容器类型都可以序列化,但是必须将安全参数指定为False
3。表单携带表单文件数据
表单必须设置的参数:
<form method="post" enctype="multipart/form-data">
</form>
后台文件代码:
files = request.FILES # 后端接收文件数据只能用FILES方法,不能用POST
4.FBV 和 CBV
FBV:基于功能的视图FBV:CB 基于视图 CBV自动匹配类中定义的方法,并根据请求方法自动执行
# views.py
from django impost views
class MyView(views.View):
def get(self, request):
return HttpResponse('我是CBV的get方法')
def post(self, request):
return HttpResponse('我是CBV的post方法')
# urls.py
path('func/', views.MyView.as_view())
5.CBV源码分析
源码分析入口:path('func/', views.MyView.as_view())
1.绑定给类的as_view()方法
def as_view(...):
def view(...):
pass
return view
此时路由匹配代码的本质:path('func/', views.view())
由此可见,CBV与FBV路由匹配的原理是一样的
2.path('func/', views.view())
这句代码的意思是:只要我们访问了func地址,会立即执行后面的views.view()
3.进入view()函数:
def view(request, *args, **kwargs):
self = cls(**initkwargs) # 这里的cls使我们自己写的类MyView self是MyView实例化出来的对象obj 这一句相当于 obj = MyView()
return self.dispatch(request, *args, **kwargs) # 这一句相当于obj.dispatch()
4.进入dispatch函数
def dispatch(self, request, *args, **kwargs):
# dispatch是绑定给对象的方法,self相当于是我们前文提到的obj
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),self.http_method_not_allowed)
# 反射 通过请求字符串去调用真正的请求方法 这里的请求是post所以handler是post
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 即post(request, *args, **kwargs)
# 此时 view()函数的返回值为:
# def view(request, *args, **kwargs):
# return self.post(request, *args, **kwargs)
模板层
1.用于传递值的模板语法
1。方法:按名称传递值。优点是资源不浪费,缺点是数值太大就不方便
def home(request):
name = 'kevin'
age = 19
return render(request, 'home.html', {'name':name, 'age': age})
2。方法:关键字 locals。您可以指定整个视图函数命名空间中的所有名称,这既简单又快捷。缺点是存在冗余
def home(request):
name = 'kevin'
age = 19
return render(request, 'home.html', locals())
2。模板语法值传递的范围
1.可以传递基本数据类型 2.函数名称 括号内自动传递,结果显示在页面上(如果函数有参数,则不会执行或显示,模板的语法不支持参数) 3、类名的传递也是在括号中自动进行的,并且被实例化。输出对象显示在页面上(模板语法自动判断每个名字是否可以带括号调用,如果可以则自动调用) 4. 传递对象时,可以直接使用点字符来显示该对象的属性。 5. Django 模板语法 操作容器类型时只能使用点字符(操作列表为.数字格式)
3。模板的语法值过滤器
该过滤器类似于python的内置函数
<p>统计长度:{{ s|length }}</p>
<p>加法运算:{{ s|add:'NB' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>数据切片:{{ s|slice:'3' }}</p>
<p>字符截取:{{ s|truncatechars:3 }}</p> # 以字符为单位 多出的部分用...代替
<p>单词截取:{{ words|truncatewords:3 }}</p> #以单词为单位 多出的部分用...代替
<p>语法转义:{{ html_tag|safe }}</p> # 识别字符串中的html标签 并渲染(默认是不识别)
html默认不识别后端传过来的字符串标签,指定safe可以让其识别并渲染
除了在传给前端之后让前端识别 我们也可以在后端处理之后再传给前端,这样前端就不用识别了(意味着html页面上的数据不一定非要在html文件中编写了 也可以通过后端传入)
from django.utils.safestring import mark_safe
script_tag1 = '<script>alert(666)</script>'
res = mark_safe(script_tag1) # 直接把res传给前端
'''
django模板语法中的符号就两个 一个{{}} 一个{%%}
需要使用数据的时候 {{}}
需要使用方法的时候 {%%}
'''
4。模板语法标签(类似python流程控制)
if 标签:
{% if 条件 %} 条件一般是后端传过来的数据 直接写名字使用即可
条件成立执行的代码
{% elif 条件1 %}
条件1成立执行的代码
{% else %}
条件都不成立执行的代码
{% endif %}
for 标签
{% for i in f %}
{% if forloop.first %}
<p>这是第一次</p>
{% elif forloop.last %}
<p>这是最后一次</p>
{% else %}
<p>啥也不是{{ i }}</p>
{% endif %}
{% empty %}
<p>你给我的是个空 怎么for循环呢</p>
{% endfor %}
一些参数可用于for循环
变量 | 描述 |
---|---|
(loop.counter1的索引值)forloop。 counter0 | 当前循环的索引值(从0开始) |
forloop.revcounter | 当前循环的反向索引值(从1开始) |
forloop.revcounter0 | |
forloop.revcounter0 | |
forloop .revcounter0 | |
是当前循环的值(从 0 开始) | |
forloop.first | 当前循环是第一个循环(逻辑值) |
forloop.last | 当前循环是最后一个循环(Bo)值) |
forloop。父循环 | 循环的外循环 |
5。自定义标签功能、过滤器、inclusion_tag
如果要实现自定义,首先要进行以下操作
1。在应用下创建一个名为 Templatetags 的文件夹 2. 在文件夹下创建一个任意名称的 .py 文件 3. 在 py 文件中编写自定义相关代码
from django.template import Library
register = Library()
自定义过滤器
@register.filter(name='myfilter')
def my_add(a, b):
return a + b
自定义标签功能
@register.simple_tag(name='mt')
def func(a, b, c, d):
return a + b + c + d
自定义clusion_tag 自定义标签使用
{% load mytag %}
{{ i|myfilter:1 }}
{% mt 1 2 3 4 %}
{% index 10 %}
6。模板继承
{% extends 'html文件名' %}
{% block 名字 %}
模板内容(将要被继承的部分)
{% endblock %}
{% block 名字 %}
子板内容
{% endblock %}
一般情况下母板中至少应该有三个区域使得扩展性更高!!! css content js
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
子板中还可以使用母板的内容 {{ block.super }}
7.模板导入
将html页面的某一部分作为模块导入
{% include 'menu.html' %}
作者:艾新觉逻辑之星
来源:稀土掘金
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。