序列化、CBV源码分析、模版层

一、JsonResponse序列化

1、json格式的数据的作用

  主要就是实现跨语言数据传输

2、不同使用场景中的json序列化

py中:

1
2
json.dumps   序列化
json.loads  反序列化

js中:

1
2
JSON.stringify()  # json.dumps
JSON.parse()      # json.loads

django中:

1
2
3
4
5
from django.http   import  JsonResponse
 
def index(request):
    d = {'username': 'kevin哈喽', 'age': 18}
    return JsonResponse(d, safe=False,json_dumps_params={'ensure_ascii': False})

ensure_ascii:默认为 True。如果将此参数设置为 False,则可以编码包含非ASCII字符的字符串,否则会进行 ASCII 编码。

通过设置safe=False,Django将允许序列化非字典类型的数据。这在您返回的数据不仅限于字典结构时非常有用,例如,您可以返回一个列表作为JSON响应。

二、form表单上传文件

1、form表单能上传文件的前提

1
2
3
4
5
<form action="" method="post" enctype="multipart/form-data">
 
1. 请求方式必须是post
 
2. enctype必须是form-data

注:

enctype是编码类型的意思。

enctype="multipart/form-data" 是 HTML 表单元素中的一个属性,用于指定在提交表单时,浏览器要使用哪种编码类型来进行数据传输。它的作用是允许在表单中传输包含二进制数据(例如文件上传)的内容。

2、views代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def sc_file(request):
 
    # 接收提交的文件数据
    # POST只能获取到post请求的普通数据,文件数据拿不到
    print(request.POST.get('username'))
    # <QueryDict: {'username': ['jack']}>
 
    print(request.FILES)  # 接收的是文件数据
    # <MultiValueDict: {'my_file': [<InMemoryUploadedFile: 10056.jpg (image/jpeg)>]}>
 
    if request.method  == 'POST':
        file_obj = request.FILES.get('my_file')
        with  open(file_obj.name, 'wb') as f:
            for line  in file_obj:
                f.write(line)
    return render(request, 'ff.html')

注:

1. 接收文件使用的是 request.FILES

2.  with open(file_obj.name, 'wb') as f: 处file_obj.name改为file_obj就会报错:

1
2
TypeError at /sc_file/
expected str, bytes or os.PathLike object, not InMemoryUploadedFile

3、html文件

1
2
3
4
5
6
7
<form action="" method="post" enctype="multipart/form-data">
    <input type="text" name="username">
    <br>
    上传文件:<input type="file" name="my_file">
    <br>
    <input type="submit" value="提交">
</form>

三、request对象的另外几个方法

1、request.FILES

1
2
3
4
5
6
7
8
request.GET
request.POST
request.FILES
 
request.path_info  #  /ab_request/
reqeust.path       #  /ab_request/
request.get_full_path() # /ab_request/  /ab_request/?username=kevin&age=11
request.body  # 它能够接收浏览器发过来的二进制数据 

四、C(class)BV的书写和F(function)BV的写法

1、CBV - Class-Based Views(基于类的视图)

CBV 是一种使用基于类的方式来实现视图的方法。它允许你将视图逻辑封装在类中,并通过类的方法来处理不同的 HTTP 请求方法(如 GET、POST 等)。

CBV 提供了很多内置的通用视图类,用于快速实现常见的 CRUD(创建、读取、更新、删除)操作。

2、FBV - Function-Based Views(基于函数的视图)

FBV 是一种使用函数的方式来实现视图的方法。在 FBV 中,每个视图都是一个独立的 Python 函数,根据不同的 HTTP 请求方法来处理请求。

在函数内部编写视图逻辑,可以通过请求对象获取用户提交的数据,然后返回 HTTP 响应。 

比较两者,CBV 提供了更多的面向对象特性和可重用性,因为它可以利用类的继承和方法重写来实现视图的复用。而 FBV 相对来说更加简单,适合处理简单的视图逻辑。

在 Django 中,你可以根据项目需求和个人偏好选择使用 CBV 或 FBV 来实现视图功能。

3、CBV视图函数的书写方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyLogin(View):
    # 类里面的方法名字不能够随便写,目前只能写get post等
    # 访问这个地址必须是get请求方式
    def get(self, request):
        # get() takes 1 positional argument but 2 were given
        print("get")
        return HttpResponse("get")
 
    # 访问这个方法必须是psot请求方式
    # 通过form表单发送post请求
    # 出了form表单,我们还可以使用工具来模拟
    def post(self,request):
        print("post")
        return HttpResponse("post")

4、在postman中提交form表单测试

注意:url要加完整的路径,后面的/浏览器回自动添加,postman不会

五、CBV的源码

1、看源码先找到源码的入口

1
path('login/', views.MyLogin.as_view()), 

注:MyLogin是自定义的类(视图层)

MyLogin.as_view() 即类调用方法

类名可以调用哪些方法:
1. 方法被@classmethod装饰器修饰的方法
  类名来调用类方法有什么特殊之处:
  会把类名自动当成第一个参数传递给方法的第一个形参cls
2. 被@staticmethod装饰器修饰的方法

2、第一步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@classonlymethod
    def as_view(cls, **initkwargs):
        # cls:MyLogin
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.setup(request, *args, **kwargs)
            if not hasattr(self, 'request'):
                raise AttributeError(
                    "%s instance has no 'request' attribute. Did you override "
                    "setup() and forget to call super()?" % cls.__name__
                )
            return self.dispatch(request, *args, **kwargs)
     
        return view

3、第二步

上一步 return 返回view

1
path('login/', View.view),

4、第三步

1
当请求来的时候,开始匹配路由login,就会调用View.view()

5、第四步

1
2
3
4
5
6
7
def view(request, *args, **kwargs):
            # self = MyLogin(**initkwargs)
            self = cls(**initkwargs)
            """
                self: MyLogin()
            """
            return self.dispatch(request, *args, **kwargs) # 这句话是最重要的

6、第五步

1
self.dispatch(request, *args, **kwargs)

7、第六步

1
找到了View类里面的dispatch方法

8、第七步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def dispatch(self, request, *args, **kwargs):
            # getattr: 反射
            # 反射
            # getattr setattr delattr hasattr
            # handler = getattr(self, 'get', self.http_method_not_allowed)
            # handler = getattr(self, 'post', self.http_method_not_allowed)
            # handler就是方法名,对象
            # hander = get
            # hander = post
            # hander = self.http_method_not_allowed
        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)

9、如何让我写的CBV类只支持get请求或者只支持post请求? 

方法重写

1
2
3
4
5
6
7
8
class MyLogin(View):
    http_method_names = ['get',]
    # 类里面的方法名字不能够随便写,目前只能写get post等
    # 访问这个地址必须是get请求方式
    def get(self, request):
        # get() takes 1 positional argument but 2 were given
        print("get")
        return HttpResponse("get")

六、模版层

模板过滤器是一种用于在模板中对数据进行处理和格式化的工具。它们以管道符(|)后跟过滤器名的形式出现,用于对模板变量进行修改或转换。

过滤器能够帮助你在模板中进行一些简单的数据处理,例如格式化日期、字符串截断、转换大小写等。

1、模板变量之分配

模板中取值一定使用的是句点符.

模板中的函数一定不能够加括号,他们会自动帮你加括号调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# views
def func(request):
    d = {'username': 'zjz', 'age': 18, 'hobby': ['喝酒', '抽烟', '打牌']}
 
    def index():
        return ('from index')
 
    return render(request, 'temp.html', context=locals())
 
 
# html文件
<div>
    <p>
        {{ d.hobby.1 }}  # 1是列表的下标
        {{ index }}
    </p>
</div>

2、模板之过滤器

1
2
语法:
    {{ obj | 过滤器名称:参数 }}  变量名字|过滤器名称:变量

date 过滤器:用于格式化日期。

1
2
<!-- 将日期对象格式化为 'Y年m月d日' 的形式 -->
{{ my_date_variable|date:'Y-m-d' }}

default 过滤器:在变量值不存在时,使用默认值。

1
2
<!-- 如果 my_variable 不存在,将显示 "Not available" -->
{{ my_variable|default:"Not available" }}

length 过滤器:获取列表或字符串的长度。

1
2
<!-- 显示 my_list 列表的长度 -->
{{ my_list|length }}

truncatechars 过滤器:截断字符串到指定长度,并在末尾添加省略号。

1
2
<!-- 将 my_string 截断到30个字符,并添加省略号 -->
{{ my_string|truncatechars:30 }}

lowerupper 过滤器:将字符串转换为小写或大写。

1
2
3
4
5
<!-- 将 my_string 转换为小写 -->
{{ my_string|lower }}
 
<!-- 将 my_string 转换为大写 -->
{{ my_string|upper }}

slice 过滤器:对列表进行切片。

1
2
3
4
5
<!-- 获取 my_list 列表的前5个元素 -->
{{ my_list|slice:":5" }}
 
<!-- 获取 my_list 列表的第2到第5个元素 -->
{{ my_list|slice:"1:5" }}

3、模版之标签

相比于模板中的变量,标签更为复杂一些,如

1
2
3
1、一些标签用来在输出中创建文本
2、一些标签用来进行流程控制(执行循环或者if判断)
3、一些标签用来将外部信息加载到模板中以供以后的变量使用

模板中的标签的格式为

1
2
3
4
5
6
7
8
9
10
# 1、
{% 标签名 %}
 
# 2、大多数标签都需要接收参数
{% 标签名 参数1 参数2 %}
 
# 3、一些标签需要有开始{% tag %}和结束标记{% endtag %}
{% 标签名 %}
...内容...
{% end标签名 %}

常用标签之for标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#1、遍历每一个元素:
{% for person in person_list %}
    <p>{{ person.name }}</p>
{% endfor %}
 
#2、可以利用{% for obj in list reversed %}反向循环。
 
#3、遍历一个字典:
{% for key,val in dic.items %}
    <p>{{ key }}:{{ val }}</p>
{% endfor %}
 
#4、循环序号可以通过{{ forloop }}显示 
forloop.counter            当前循环的索引值(从1开始)
forloop.counter0           当前循环的索引值(从0开始)
forloop.revcounter         当前循环的倒序索引值(从1开始)
forloop.revcounter0        当前循环的倒序索引值(从0开始)
forloop.first              当前循环是第一次循环则返回True,否则返回False
forloop.last               当前循环是最后一次循环则返回True,否则返回False
forloop.parentloop         本层循环的外层循环
 
#5、for标签可以带有一个可选的{% empty %} 从句,在变量person_list为空或者没有被找到时,则执行empty子句
{% for person in person_list %}
    <p>{{ person.name }}</p>
 
{% empty %}
    <p>sorry,no person here</p>
{% endfor %}
 
了解:Django框架的for循环,没有breakcontinue方法,可以使用自定义过滤器实现forloop | continue和forloop | break,参考:https://djangosnippets.org/snippets/2093/

常用标签之if标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 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判断。
 
#4、判断条件中可以引入过滤器
{% if athlete_list|length > 1 %}
   Team: {% for athlete in athlete_list %} ... {% endfor %}
{% else %}
   Athlete: {{ athlete_list.0.name }}
{% endif %}
 
过滤器length返回的数字可用于与数字进行比较,除此之外大多数过滤器返回的都是字符串并不能用于与数字比较
 
#5、补充标签firstof
针对下述多分支
    {% if var1 %}
        {{ var1 }}
    {% elif var2 %}
        {{ var2 }}
    {% elif var3 %}
        {{ var3 }}
    {% endif %}
 
可以简写为一行
    {% firstof var1 var2 var3 %}
 
也可以定义一个备用值,当var1、var2、var3均无值的时使用
{% firstof var1 var2 var3 "fallback value" %}

常用标签之with标签

1
2
3
4
5
6
7
d = {'username':'kevin','age':18,'info':'这个人有点意思','hobby':[111,222,333,{'info':'NB'}]}
 
{% with d.hobby.3.info as nb  %}
    <p>{{ nb }}</p>
    在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式
    <p>{{ d.hobby.3.info }}</p>
{% endwith %}

常用标签之csrf_token标签

1
2
3
4
5
6
7
8
9
10
11
12
# 当用form表单提交POST请求时必须加上标签{% csrf_token%},该标签用于防止跨站伪造请求
<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>
# 具体工作原理为:
# 1、在GET请求到form表单时,标签{% csrf_token%}会被渲染成一个隐藏的input标签,该标签包含了由服务端生成的一串随机字符串,如<input type="hidden" name="csrfmiddlewaretoken" value="dmje28mFo...OvnZ5">
# 2、在使用form表单提交POST请求时,会提交上述随机字符串,服务端在接收到该POST请求时会对比该随机字符串,对比成功则处理该POST请求,否则拒绝,以此来确定客户端的身份
 
# ps:什么是跨站请求伪造(英语:Cross-site request forgery)详见附录2

七、模版层之继承(重要)

继承:继承之后的页面跟被继承的页面一模一样

继承之后,要自己在基础html页面中划分要修改的区域,继承一方进行修改

1、关键字 extends

在子页面书写,xxx.html为父页面

1
{% extends 'xxx.html' %}

2、关键字  block 

block可以包裹任意一个块,也可以是一个空的地方

content为某一个块的名字

1
2
3
4
5
{% block content %}
    <h1>日子常新,未来可期!</h1>
    <p>人间烟火,山河远阔,无一是你,无一不是你</p>
    <p><a class="btn btn-primary btn-lg" href="#" role="button">诗和远方</a></p>
{% endblock %}

3、子页面为某一个标签设置css(js 也一样)

在主页面划分一个空的block,子页面中使用block写css

1
2
3
{% block css %}
 
{% endblock %}

4、模板的导入

在一个页面导入另一个页面

1
{% include 'hello.html' %}

5、bootstrap扣组件案例

 

posted @   凡人半睁眼  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示