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

一、JsonResponse序列化

1、json格式的数据的作用

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

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

py中:

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

js中:

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

django中:

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表单能上传文件的前提

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

1. 请求方式必须是post

2. enctype必须是form-data

注:

enctype是编码类型的意思。

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

2、views代码

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就会报错:

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

3、html文件

<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

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视图函数的书写方式

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、看源码先找到源码的入口

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

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

MyLogin.as_view() 即类调用方法

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

2、第一步

@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

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

4、第三步

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

5、第四步

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

6、第五步

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

7、第六步

找到了View类里面的dispatch方法

8、第七步

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请求? 

方法重写

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、模板变量之分配

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

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

# 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、模板之过滤器

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

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

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

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

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

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

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

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

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

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

<!-- 将 my_string 转换为小写 -->
{{ my_string|lower }}

<!-- 将 my_string 转换为大写 -->
{{ my_string|upper }}

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

<!-- 获取 my_list 列表的前5个元素 -->
{{ my_list|slice:":5" }}

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

3、模版之标签

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

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

模板中的标签的格式为

# 1、
{% 标签名 %}

# 2、大多数标签都需要接收参数
{% 标签名 参数1 参数2 %}

# 3、一些标签需要有开始{% tag %}和结束标记{% endtag %}
{% 标签名 %}
...内容...
{% end标签名 %}

常用标签之for标签

#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循环,没有break和continue方法,可以使用自定义过滤器实现forloop | continue和forloop | break,参考:https://djangosnippets.org/snippets/2093/

常用标签之if标签

# 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标签

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标签

# 当用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为父页面

{% extends 'xxx.html' %}

2、关键字  block 

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

content为某一个块的名字

{% 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

{% block css %}

{% endblock %}

4、模板的导入

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

{% include 'hello.html' %}

5、bootstrap扣组件案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">Brand</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>
            </ul>
            <form class="navbar-form navbar-left">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="Search">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-3">
            <div class="list-group">
                <a href="#" class="list-group-item active">
                    起点
                </a>
                <a href="/login/" class="list-group-item">登录</a>
                <a href="/register/" class="list-group-item">注册</a>
                <a href="/bq/" class="list-group-item">回原点</a>
            </div>
        </div>
        <div class="col-md-9">
            <div class="panel panel-primary">
                <div class="panel-heading">Panel heading without title</div>
                <div class="panel-body">
                    <div class="jumbotron">
                        {% block  content   %}
                            <h1>永远十八,永远热泪盈眶!</h1>
                            <p>人间烟火,山河远阔,无一是你,无一不是你</p>
                            <p><a class="btn btn-primary btn-lg" href="#" role="button">诗和远方</a></p>
                        {% endblock %}
                        <div class="row">
                            <div class="col-sm-6 col-md-4">
                                <div class="thumbnail">
                                    <img src="https://th.bing.com/th/id/R.1363fff14ac660729966b15ed3ad0613?rik=Clu%2bvv4ZhfF3xA&riu=http%3a%2f%2fimg.ts.cn%2f003%2f523%2f914%2f00352391449_110e6504.jpg&ehk=pAoDU5Z5PM%2bAGGTi%2fjFpRneEpsghtBugLhmPAgZ%2fYMg%3d&risl=&pid=ImgRaw&r=0"
                                         alt="...">
                                    <div class="caption">
                                        <h3>海棠未雨</h3>
                                        <p>...</p>
                                        <p><a href="#" class="btn btn-primary" role="button">Button</a> <a href="#"
                                                                                                           class="btn btn-default"
                                                                                                           role="button">Button</a>
                                        </p>
                                    </div>
                                </div>
                            </div>
                            <div class="col-sm-6 col-md-4">
                                <div class="thumbnail">
                                    <img src="https://th.bing.com/th/id/R.373fa8856674ed20fdbcc32548f907b4?rik=Xm0QJfBfZEhuDQ&riu=http%3a%2f%2fimg.mp.itc.cn%2fupload%2f20160908%2f9856d4f910aa40588853e64d5123521d_th.jpg&ehk=HCDdYJ5YRQTkxi4wiVKU36n9ssllHBEE0qyZrk9y%2bwo%3d&risl=&pid=ImgRaw&r=0"
                                         alt="...">
                                    <div class="caption">
                                        <h3>梨花先雪</h3>
                                        <p>...</p>
                                        <p><a href="#" class="btn btn-primary" role="button">Button</a> <a href="#"
                                                                                                           class="btn btn-default"
                                                                                                           role="button">Button</a>
                                        </p>
                                    </div>
                                </div>
                            </div>
                            <div class="col-sm-6 col-md-4">
                                <div class="thumbnail">
                                    <img src="https://image.scol.com.cn/data/attachment/forum/202006/22/162921a691l373kgvlgqkb.jpg"
                                         alt="...">
                                    <div class="caption">
                                        <h3>一半春休</h3>
                                        <p>...</p>
                                        <p><a href="#" class="btn btn-primary" role="button">Button</a> <a href="#"
                                                                                                           class="btn btn-default"
                                                                                                           role="button">Button</a>
                                        </p>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

    </div>

</div>


</body>
</html>

 

posted @ 2023-08-01 14:44  凡人半睁眼  阅读(25)  评论(0编辑  收藏  举报