Django回顾3

一.视图层

1响应对象

响应本质都是HTTPResponse


-HttpResponse   ----->   字符串

-render   ----->   放个模板,模板渲染是在后端完成

        js代码是在客户端浏览器里执行的

        模板语法是在后端执行的

-redirect   ----->   重定向

        字符串参数部分是空的

        状态码是3开头

-JsonResponse   ----->   json格式数据

        return JsonResponse({name:xxx,age:xx})

        本质是把传入的字典或列表(必须指定safe=False),使用json序列化得到json格式字符串,最终做成HttpResponse返回给前端,如果想要给json序列化的时候传参数,必须使用json_dumps_params字典传入

        如果想往响应头中写数据,需要传headers={'xx':'xx'}

2.JsonResponse源码分析

return JsonResponse({name:xxx,age:xx})     
# 触发  JsonResponse的__init__--->{name:xx,age:xx}给了data
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,json_dumps_params=None, **kwargs):
    # 如果传入的是字典
    # safe是True,后面是False,条件不符合,内部就不会走
    if safe and not isinstance(data, dict):
        raise TypeError(
            'In order to allow non-dict objects to be serialized set the '
            'safe parameter to False.'
        )
   if json_dumps_params is None: # 条件符合
        json_dumps_params = {}
        # kwargs是字典---》setdefault--》有则修改,无则新增
        kwargs.setdefault('content_type', 'application/json')
        # 核心---》把字典转成json格式字符串,赋值给data
   data = json.dumps(data, cls=encoder, **json_dumps_params)
   # super().__init__ 调用父类的 __init__ 完成实例化---》HttpResponse的对象
   return HttpResponse(data,**kwargs)
   super().__init__(content=data, **kwargs)


# isinstance
	-isinstance(对象, 类) 判断这个对象,是不是这个类的对象

3.CBV和FBV

FBV:基于函数的视图(之前使用的全是FBV)

CBV:基于类的视图(后面经常使用)

CBV格式:

from django.views import View
class UserView(View):
    # 写方法---》跟请求方式同名的方法
    def get(self,request,*args,**kwargs)
    	必须返回四件套

路由配置:

path('index/', 视图类名.as_view()) # as_view是类的绑定方法

源码分析:

path('index/', index),--->请求来了,路由匹配成功会执行 index(request,) 
path('index/', UserView.as_view()),
# 1 入口:路由---》as_view来开始
	-请求来了,路由匹配成功---》执行---》UserView.as_view()(request)
    -需要看as_view()执行结果是什么--》view--》代码如下
        def view(request, *args, **kwargs): # 方法,可以加括号调用
           return self.dispatch(request, *args, **kwargs)
    -本质就是在执行 view(request)
    -本质在执行---》self.dispatch(request, *args, **kwargs)
    -去类(UserViwe类中找,找不到,去父类View)中找dispatch,代码如下
    def dispatch(self, request, *args, **kwargs):
        # request当次请求的请求对象,取出请求方式【假设是get请求】,转成小写 'get'
        # http_method_names = ['get', 'post', 'put']
        # 条件成立,执行if内部代码
        if request.method.lower() in self.http_method_names:
            #getattr:反射---》通过字符串去对象中取属性或方法
            # self是谁的对象? 是View这个类的对象,这个是视图类UserView的对象
            # 取出来的handler 是 UserView这个类的get方法
            handler = getattr(self, 'get')
        else:
            handler = self.http_method_not_allowed
        # handler是 UserView这个类的get方法
        # get(request)---》触发UserView这个类的get方法---》真正执行原来视图函数的内容
        # 最终返回
        return handler(request, *args, **kwargs)

总结:写CBV,只需要在视图类中写跟请求方式同名的方法即可,不同请求方式会执行不同的方法

4.self问题

class Animal:
    def run(self):
        # 这个self,是谁调用,就是谁
        print(type(self))
        print(self.name, '走路')


class Person(Animal):
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def __init__(self, name,age):
        self.name = name
        self.age=age
# p = Person('lqz')
# p.run()  #

dog=Dog('小奶狗',6)
dog.run()

self是谁调用的,self就是谁,不能只看是哪个类,以后看到self方法的时候不要只从当前类或父类中找,应该先确定当前self是谁,然后从这个对象的类根上开始找

5.上传文件

## 关于模板查找路径是配置文件中
TEMPLATES    --->'DIRS': [os.path.join(BASE_DIR, 'templates')]


## python
class FileView(View):
    def get(self,request):
        return render(request,'file.html')
    def post(self,request):
        # 拿出文件对象
        my_file=request.FILES.get('myfile')
        print(type(my_file)) #django.core.files.uploadedfile.InMemoryUploadedFile 跟之前用的文件对象不一样但是,它应该继承了文件
        from django.core.files.uploadedfile import InMemoryUploadedFile
        # 1 保存  2 取出文件名字
        # my_file.save() #找了一顿,没有,所以不能使用快捷保存方式,需要自己写保存
        print(my_file.name) # 3-回顾django.md
        # 自己写保存,放在项目根路径下
        with open(my_file.name,'wb') as f:
            for line in my_file:
                f.write(line)
        return HttpResponse('上传成功')
    
    
    
# html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="myfile">
    <br>
    <input type="submit" value="提交">
</form>
</body>
</html>

二.模板

1.模板介绍

模板在浏览器中是运行不了的,因为有模板语法,浏览器解析不了模板语法

模板必须在后端渲染完成(替换完成)变成纯粹的html、css、js

这种在后端会被渲染的类python语法就叫做模板语法

2.了解

# Django模板修改的视图函数

from django.template import Template,Context
now=datetime.datetime.now()
# 内部打开了这个模板---》读出所有内容,实例化得到了t对象
t=Template('<html><body>现在时刻是:<h1>{
  {current_date}}</h1></body></html>')
# #t=get_template('current_datetime.html')
c=Context({'current_date':str(now)})
html=t.render(c)
return HttpResponse(html)


# 另一种写法(推荐)

import datetime
now=datetime.datetime.now()
return render(req, 'current_datetime.html', {'current_date':str(now)[:19]})

3.静态化页面

  • 什么是静态化页面?
    • 将动态渲染生成的页面结果保存成html文件放到静态文件服务器中,用户直接去静态服务器访问处理好的静态html文件
  • 为什么要做页面静态化?
    • 减少数据库查询次数
    • 提高项目并发量
    • 提升页面响应效率(减少页面渲染)
  • 哪些页面要做成静态化?
    • 访问量大的页面,例如首页

4.模板语法

变量:{ { 变量名 }}   字典,列表,对象等通过.拿到属性或方法

字典:dic.name   ------->   在python中是   dic['name']   dic.get('name')

列表:list.0   --------->   在python中是   list[0]

对象:person.name  ------>  是python语法

           person.run  ------>  不是python语法,在python中是  person.run()

5.过滤器

语法:

{
  {obj|filter__name:param}}  变量名字|过滤器名称:变量

length

# 返回值的长度,对字符串和列表都起作用

{
  { value|length }}

date

# 如果value=datetime.datetime.now()

{
  { value|date:"Y-m-d"}}

safe

# Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义

value="<a href="">点击</a>"
{
  { value|safe}}

6.标签

标签看起来像是这样的: {% tag %} 标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。 一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})

 for 标签

# 遍历每一个元素,可以利用{% for obj in list reversed %}反向完成循环。

{% for person in person_list %}
    <p>{
  { person.name }}</p>
{% endfor %}


# 遍历一个字典

{% for key,value in dic.items %}
    <p>{
  { key }}:{
  { value }}</p>
{% endfor %}

if 标签

# {% if %}会对一个变量求值,如果它的值是True(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。

{% if num > 100 or num < 0 %}
    <p>无效</p>
{% elif num > 80 and num < 100 %}
    <p>优秀</p>
{% else %}
    <p>一般</p>
{% endif %}

if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

7.模板导入和继承

模板导入:

  语法:{% include '模版名称' %}

  如:{% include 'adv.html' %}
<div class="adv">
    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">Panel title</h3>
        </div>
        <div class="panel-body">
            Panel content
        </div>
    </div>
    <div class="panel panel-danger">
        <div class="panel-heading">
            <h3 class="panel-title">Panel title</h3>
        </div>
        <div class="panel-body">
            Panel content
        </div>
    </div>
    <div class="panel panel-warning">
        <div class="panel-heading">
            <h3 class="panel-title">Panel title</h3>
        </div>
        <div class="panel-body">
            Panel content
        </div>
    </div>
</div>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    {#    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">#}
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .header {
            height: 50px;
            width: 100%;
            background-color: #369;
        }
    </style>
</head>
<body>
<div class="header"></div>

<div class="container">
    <div class="row">
        <div class="col-md-3">
            {% include 'adv.html' %}


        </div>
        <div class="col-md-9">
            {% block conn %}
                <h1>你好</h1>
            {% endblock %}

        </div>
    </div>

</div>

</body>
</html>
{% extends 'base.html' %}

{% block conn %}
    {
  { block.super }}
是啊

{% endblock conn%}

模板继承:

Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks 。

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css"/>
    <title>{% block title %}My amazing site{% endblock %}</title>
</head>

<body>
<div id="sidebar">
    {% block sidebar %}
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
    {% endblock %}
</div>

<div id="content">
    {% block content %}{% endblock %}
</div>
</body>
</html>

这个模版,我们把它叫做base.html, 它定义了一个可以用于两列排版页面的简单HTML骨架。“子模版”的工作是用它们的内容填充空的blocks。

在这个例子中,blosk标签定义了三个可以被子模版内容填充的block。block告诉模版引擎: 子模版可能会覆盖掉模版中的这些位置。

子模版可能看起来是这样的:

{% extends "base.html" %}
 
{% block title %}My amazing blog{% endblock %}
 
{% block content %}
{% for entry in blog_entries %}
    <h2>{
  { entry.title }}</h2>
    <p>{
  { entry.body }}</p>
{% endfor %}
{% endblock %}

extends标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时,首先,它将定位父模版——在此例中,就是“base.html”。

那时,模版引擎将注意到base.html 中的三个block标签,并用子模版中的内容来替换这些block。根据blog_entries的值,输出可能看起来是这样的:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>My amazing blog</title>
</head>
 
<body>
    <div id="sidebar">
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
    </div>
 
    <div id="content">
        <h2>Entry one</h2>
        <p>This is my first entry.</p>
 
        <h2>Entry two</h2>
        <p>This is my second entry.</p>
    </div>
</body>
</html>
请注意,子模版并没有定义 `sidebar` block,所以系统使用了父模版中的值。父模版的 `{% block %}` 标签中的内容总是被用作备选内容(fallback)。

这种方式使代码得到最大程度的复用,并且使得添加内容到共享的内容区域更加简单,例如,部分范围内的导航。

**这里是使用继承的一些提示**:

>- 如果你在模版中使用 `{% extends %}` 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。
>
>- 在base模版中设置越多的 `{% block %}` 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。
>
>- 如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 `{% block %}` 中。
>
>- If you need to get the content of the block from the parent template, the `{
  { block.super }}` variable will do the trick. This is useful if you want to add to the contents of a parent block instead of completely overriding it. Data inserted using `{
  { block.super }}` will not be automatically escaped (see the next section), since it was already escaped, if necessary, in the parent template.
>
>- 为了更好的可读性,你也可以给你的 `{% endblock %}` 标签一个 *名字* 。例如:
>
>  {%block content %}...{%endblock content %}
>
>  在大型模版中,这个方法帮你清楚的看到哪一个  `{% block %}` 标签被关闭了。
>
>- 不能在一个模版中定义多个相同名字的 `block` 标签。

相关推荐

  1. Django回顾3

    2023-12-07 03:36:01       38 阅读
  2. Django回顾

    2023-12-07 03:36:01       52 阅读
  3. Django回顾4

    2023-12-07 03:36:01       37 阅读
  4. Django回顾【六 】

    2023-12-07 03:36:01       36 阅读
  5. Django回顾【三】

    2023-12-07 03:36:01       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-07 03:36:01       75 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-07 03:36:01       80 阅读
  3. 在Django里面运行非项目文件

    2023-12-07 03:36:01       64 阅读
  4. Python语言-面向对象

    2023-12-07 03:36:01       75 阅读

热门阅读

  1. [Electron] 将应用日志文件输出

    2023-12-07 03:36:01       54 阅读
  2. 【debug】Image 库 字体问题

    2023-12-07 03:36:01       47 阅读
  3. React使用echarts并且修改echarts图大小

    2023-12-07 03:36:01       51 阅读
  4. 解释 Git 的基本概念和使用方式

    2023-12-07 03:36:01       39 阅读
  5. php使用CORS解决跨域

    2023-12-07 03:36:01       43 阅读
  6. git-6

    git-6

    2023-12-07 03:36:01      63 阅读
  7. python起步

    2023-12-07 03:36:01       54 阅读
  8. SpringBoot常用注解

    2023-12-07 03:36:01       58 阅读