Django框架入门教程:网页伪静态、视图层与模板层

2022-09-1809:20:00后端程序开发Comments940 views字数 5648阅读模式

网页伪静态

将动态网页伪装成静态网页,可以提升网页被搜索引擎检索道德概率
表现形式为:网址看着像是一个具体的文件路径例如:http://127.0.0.1:8001/admin/login/
path('index.html', views.index)

视图层

1.视图函数的返回值问题

当我们在views.py定义的视图函数不设置返回值时,可以看到django报了以下错误:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

Django框架入门教程:网页伪静态、视图层与模板层文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

报错信息:The view app01.views.home didn't return an HttpResponse object. It returned None instead. 视图app01.views.home没有返回HttpResponse对象。它返回None

由此我们可以猜测一个结论:视图函数必须返回一个HttpResponse对象 我们ctrl+左键进入HttpResponse可以发现它是一个类:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

class HttpResponse(HttpResponseBase):
	pass

可是视图函数还可以返回render和redirect对象啊,我们进入到这两个函数中一探究竟:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

def render(...):
    pass
    return HttpResponse(content, content_type, status)

render函数返回值也是HttpResponse对象。 再来看看redirect:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

def redirect(to, *args, permanent=False, **kwargs):
    redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
    return redirect_class(resolve_url(to, *args, **kwargs))

redirect函数返回值也是HttpResponse对象。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

由此可见,views.py中的视图函数都必须返回一个HttpResponse对象文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

2.视图函数返回json格式数据

需求:将字典数据序列化成json字符串传给前端::文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

方法1:利用json模块文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

def home(request):
    import json
    user_dict = {'name': 'jason老师', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
    json_user_dict = json.dumps(user_dict, ensure_ascii=False)
    return render(request, 'home.html', json_user_dict)

方法2:利用JsonResponse文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

from django.http import JsonResponse
def home(request):
    JsonResponse(user_dict)  # 

只用一行代码就顶替了上述方法三行代码,非常好用。但有个问题,JsonResponse没有ensure_ascii参数,也就意味着我们暂时无法阻止汉字编码。想要解决这个问题,主要我们查看JsonResponse的源码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

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的值,以字典的形式传入。于是:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False})

这就相当于我们设置了**'ensure_ascii':False** 但是设置这个参数的过程属实有点坎坷~~文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

除了字典类型,其他容器类型也可以被序列化,不过要指定safe参数为False文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

3.form表单携带文件数据

form表单需要设置的参数:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

<form method="post" enctype="multipart/form-data">
    
</form>

后端获取文件代码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

files = request.FILES  # 后端接收文件数据只能用FILES方法,不能用POST

4.FBV与CBV

FBV:基于函数的视图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

# views.py
def home(request):
    return render(request, 'home.html')
# urls.py
path('home/', views.home)

CBV:基于类的视图 CBV会根据请求方式的不同自动匹配类中定义的方法并自动执行文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

# 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:指名道姓地传值。好处是不浪费资源,坏处是值过多时不方便文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

def home(request):
    name = 'kevin'
    age = 19
    return render(request, 'home.html', {'name':name, 'age': age})

方式2:关键字locals()。可以将整个视图函数名称空间中所有的名字全部传入,简单快捷,坏处是有冗余文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

def home(request):
    name = 'kevin'
    age = 19
    return render(request, 'home.html', locals())

2.模板语法传值的范围

1.基本数据类型都可以传递 2.函数名的传递会自动加括号执行并将结果展示到页面上(注意函数如果有参数则不会执行也不会展示,模板语法不支持参数) 3.类名的传递也会自动加括号调用并将实例化出的对象展示到页面上(模板语法会自动判断每一个名字是否能被加括号调用,如果可以则自动调用) 4.对象的传递可以直接用句点符点出对象的属性 5.django的模板语法在操作容器类型时只能用句点符操作(操作列表用 .数字 的形式)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

3.模板语法值过滤器

过滤器类似于python中的内置函数文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

    <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框架入门教程:网页伪静态、视图层与模板层文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

'''
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循环可用的一些参数文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

VariableDescription
forloop.counter当前循环的索引值(从1开始)
forloop.counter0当前循环的索引值(从0开始)
forloop.revcounter当前循环的倒序索引值(从1开始)
forloop.revcounter0当前循环的倒序索引值(从0开始)
forloop.first当前循环是不是第一次循环(布尔值)
forloop.last当前循环是不是最后一次循环(布尔值)
forloop.parentloop本层循环的外层循环

5.自定义标签函数、过滤器、inclusion_tag

如果想实现自定义,必须先做以下几件事文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

1.在应用下创建一个名为templatetags的文件夹 2.在该文件夹下创建任意名称的.py文件 3.在该py文件内编写自定义相关代码文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

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

自定义inclusion_tag

@register.inclusion_tag(filename='it.html')
    def index(n):
        html = []
        for i in range(n):
            html.append('第%s页'%i)
        return locals()

自定义标签的使用

{% 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页面的某个部分以模块的形式导入文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

{% include 'menu.html' %}

作者:爱新觉罗吉星
来源:稀土掘金文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/27716.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/27716.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定