网页伪静态

将动态网页伪装成静态网页 从而提升网页被搜索引擎的概率
表现形式就是网址看着像一个具体的文件路径

path('index.html',view.index)

视图层

一、视图函数的返回值问题
视图函数必须返回一个HttpResponse对象
研究码源发现HttpResponse其实是一个类
    class HttpResponse(HttpResponseBase):
        pass
    def render():
        return HttpResponse(...)
    def redirect(to, *args, permanent=False, **kwargs):
        redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
        return redirect_class(resolve_url(to, *args, **kwargs))
二、视图函数返回的json格式数据
  • 使用json模块
import json
def func(request):
    user_dict = {'name': 'jason', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
    json_str = json.dumps(user_dict, ensure_ascii=False)  # ensure_ascii=False显示中文,不设置此参数就会以二进制字节展示
    return HttpResponse(json_str)
  • 用django自带JsonResponse模块
from django.http import JsonResponse
def func(request):
    user_dict = {'name': 'jason', 'pwd': 123, 'hobby': ['read', 'run', 'music']}
    return JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False})  # json_dumps_params={'ensure_ascii':False}显示中文
  • 序列化非字典类型的数据还需要指定safe参数为False
from django.http import JsonResponse
def func(request):
    user_hobby = ['read', 'run', 'music']
    return JsonResponse(user_hobby, safe=False, json_dumps_params={'ensure_ascii':False})  # json_dumps_params={'ensure_ascii':False}显示中文
三、form表单携带文件数据
  • form表单上传文件类型的数据
    1.method必须指定成post
    2.enctype属性值必须是multipart/form-data
"""
后端获取文件数据的操作
    request.FILES
"""
def index(request):
    if request.method == 'POST':
        file_obj = request.FILES.get('file')  # file就是我们在前端form表单下的input中name属性设置的名字
        with open(file_obj.name, 'wb') as f:  # file_obj.name就可以点出文件的名字
            for line in file_obj:
                f.write(line)
    return render(request, 'index.html') # 还可以上传视频

# 前端代码
<form action="" method="post" enctype="multipart/form-data">
    <p><input type="file" name="file"></p>
    <p><input type="submit" value="提交"></p>
</form>
四、FBV与CBV

视图函数既可以是函数 也可以是类

  • 1.FBV:基于函数的视图
# 视图
def index(request):
    return HttpResponse()

# 路由
    path('index/', views.index)
  • 2.CBV:基于类的视图
# 视图
from django import views
class MyView(views.View):
    def get(self, request):
        return HttpResponse('我是CBV里面的get方法')
    def post(self, request):
        return HttpResponse('我是CBV里面的post方法')
# 路由
    path('func/', views.MyView.as_view())
"""
CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行
"""
五、CBV源码分析(重要)
# 突破口在urls.py
url(r'^login/',views.MyLogin.as_view())
# url(r'^login/',views.view)  FBV一模一样
# CBV与FBV在路由匹配上本质是一样的 都是路由 对应 函数内存地址
"""
函数名/方法名 加括号执行优先级最高
猜测
    as_view()
        要么是被@staicmethod修饰的静态方法
        要么是被@classmethod修饰的类方法  正确
    @classonlymethod
    def as_view(cls, **initkwargs):
        pass
"""
    @classonlymethod
    def as_view(cls, **initkwargs):
        """
        cls就是我们自己写的类   MyCBV
        Main entry point for a request-response process.
        """
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)  # cls是我们自己写的类
            # self = MyLogin(**initkwargs)  产生一个我们自己写的类的对象
            return self.dispatch(request, *args, **kwargs)
            """
            以后你们会经常需要看源码 但是在看python源码的时候 一定要时刻提醒自己面向对象属性方法查找顺序
                先从对象自己找
                再去产生对象的类里面找
                之后再去父类找
                ...
            总结:看源码只要看到了self点一个东西 一定要问你自己当前这个self到底是谁
            """
        return view

# CBV的精髓
    def dispatch(self, request, *args, **kwargs):
        # 获取当前请求的小写格式 然后比对当前请求方式是否合法
        # get请求为例
        # post请求
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            """
            反射:通过字符串来操作对象的属性或者方法
                handler = getattr(自己写的类产生的对象,'get',当找不到get属性或者方法的时候就会用第三个参数)
                handler = 我们自己写的类里面的get方法
            """
        else:
            handler = self.http_method_not_allowed
            return handler(request, *args, **kwargs)
        """
        自动调用get方法
        """

模板层

一、模板语法传值
  • 方式一:指名道姓(指名道姓传参 不浪费资源)
'''
django模板语法中的符号就两个 一个{{}} 一个{%%}
    需要使用数据的时候 {{}}
    需要使用方法的时候 {%%}
'''
# 后端
    name = 'jason'
    return render(request, 'modal.html', {'name':name})
# 前端
    {{ name }} # 可以直接使用后端name
  • 方式二:关键字locals(将整个局部名称空间的名字全部传入 简单快捷)
# 后端
    def func(request):
        name = 'jason'
        age = 18
        hobby = 'read'
        return render(request,'modal.html',locals())
# 前端
    {{ name }} {{ age }} {{gender}} {{request}} # 后端有的都可以直接使用
二、模板语法传值的范围
1.python基本数据类型直接传递使用
2.函数名的传递会自动加括号执行并将返回值展示到页面上 没有返回值就是None
    注意函数如果有参数则不会执行也不会展示 模板语法不支持有参函数
3.类名的传递也会自动加括号产生对象并展示到页面上
    对象的传递则直接使用即可
ps:模板语法会判断每一个名字是否可调用 如果可以则调用!!!
"""
django的模板语法在操作容器类型的时候只允许使用句点符
"""

代码演示

# urls.py
path('test2/',views.test2)

# views.py
def aaa():
    return 'aaa'

class Person:
    def __init__(self):
        pass

def test2(request):
    p=Person     # 类
    p1=Person()  # 对象
    a=aaa        # 函数名
    return render(request,'test2.html',locals())

# html页面
<body>
<h3>{{ p }}</h3>
<h3>{{ p1 }}</h3>
<h3>{{ a }}</h3>
</body>
三、模板语法过滤器(类似于python内置函数)
import datetime
def filter1(request):
    a='hello,world!'
    b=10
    c=datetime.datetime.today()
    d=23232323232
    e=[1,2,3,4,5,6]
    f='my name is jason'
    css_tag='<i>你好</i>'
    script_tag='<script>alert(123)</script>'

    # 语法转义第二种方式
    from django.utils.safestring import mark_safe
    res=mark_safe('<script>alert(333)</script>')
    return render(request,'filter.html',locals())
<p>统计长度:{{ s|length }}</p>  # 计算s的长度
<p>加法运算:{{ i|add:123 }}、加法运算:{{ s|add:'heiheihei' }}</p>  # 加法运行 还支持字符串拼接
<p>日期转换:{{ s|date:'Y-m-d H:i:s' }}</p>  # 将日期按照指定的格式展示
<p>文件大小:{{ file_size|filesizeformat }}</p>  # 判断该文件的大小
<p>数据切片:{{ l|slice:'0:10' }}</p>  # 将数据索引0到索引10进行切片 顾头不顾尾
<p>字符截取:{{ s1|truncatechars:6 }}</p>  # 展示6个字节内容 三个点算一个
<p>单词截取(空格):{{ s1|truncatewords:6 }}</p> 
<p>语法转义:{{ script_tag|safe }}</p>
<p>语法转义:{{ script_tag1|safe }}</p>
from django.utils.safestring import mark_safe
script_tag1 = '<script>alert(666)</script>'
res = mark_safe(script_tag1)

PS:有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入
四、模板语法标签(类似于python流程控制)
  • if判断
{% if 条件 %}   # 条件一般是模板语法传过来的数据  直接写名字使用即可
     <h1>我是if</h1>    # 条件成立执行的代码
{% elif 条件1 %}
     <h1>我是elif</h1>  # 条件1成立执行的代码
{% else %}
     <h>我是else</h>    # 条件都不成立执行的代码
{% endif %}
  • for循环
{% for i in s %}
      <p>{{ i }}</p>
{% endfor %
  • for循环+if判断
{% for foo in lll %}
    {% if forloop.first %}
        <p>这是我的第一次</p>
    {% elif forloop.last %}
        <p>这是最后一次啊</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
    {% empty %}
        <p>for循环的可迭代对象内部没有元素 根本没法循环</p>
{% endfor %}

with起别名

{% with d.hobby.3.info as nb  %}
	<p>{{ nb }}</p>在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式
	<p>{{ d.hobby.3.info }}</p>
{% endwith %}
五、自定义标签函数、过滤器、inclusion_tag

如果想自定义 必须先做以下三件事
1.在应用下创建一个名为templatetags文件夹
2.在该文件夹创建任意名称的py文件
3.在该py文件内编写自定义相关代码

  • 1.自定义过滤器
    在templatetags文件夹创建一个mytag的py文件
from django.template import Library
register=Library()
@register.filter(name='myfilter')
def my_add(a, b):
    return a + b

# 前端页面需要先导入mytag
    {% load mytag %}
    {{ i|myfilter:1 }}
  • 2.自定义标签函数
@register.simple_tag(name='mt')
def func(a, b, c, d):
    return a + b + c + d

# 使用
    {% load mytag %}
    {% mt 1 2 3 4 %}
  • 3.自定义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 %}
    {% index 10 %}
六、模板的继承
{% extends '要继承html文件名' %}
    {% block 名字 %}
        模板内容
    {% endblock %}
    {% block 名字 %}
        子板内容
    {% endblock %}
"""
一般情况下母板中至少应该有三个区域使得扩展性更高:css content js
"""
# css
{% block css %}
    # css代码区
{% endblock %}

# content
{% block content %}
    # 内容区
{% endblock %}

# js
{% block js %}
    # js代码区
{% endblock %}
'''子板中还可以使用母板的内容  {{ block.super }} '''
七、模板的导入(了解)

将html页面的某个部分当做模块的形式导入使用

{% include '要导入的html文件' %}
 posted on 2022-09-04 20:48  Joker_Ly  阅读(6)  评论(0)    收藏  举报