django学习笔记

今日内容概要

  • 网页伪静态
  • 视图层
  • 模板层

今日内容详细

网页伪静态

动态页面:用ASP、PHP、JSP、ASP.net、Perl、或CGI等编程语言制作,不是独立存在于服务器上的网页文件,只有当用户请求时服务器才返回一个完整的网页,内容存在于数据库中,根据用户发出的不同请求,其提供个性化的网页内容。

静态页面:静态页面的URL链接是以.html、htm、.shtml、.xml为链接后缀,存在于服务器上的一个文件,每个网页都是一个独立的文件,内容直接保存在文件中,没有连接数据库。

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

伪静态好处:把网页做成伪静态最主要的就是为了搜索引擎方便搜索引擎蜘蛛(Spider)来抓取网页上的相关内容;提高用户对网页的信任度,因为伪静态的后缀也是.html .htm .shtml .xml;网页静态化也影响着网站在搜索引擎的排名;伪静态明确了网站的URL链接,可以更好的让用户传播、浏览以及输入;伪静态不需要全站生成静态页面,可节省服务器空间使用率。

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

视图层

视图函数的返回值

视图函数必须返回一个HttpResponse对象。(HttpResponse其实是一个类)

HttpResponse

class HttpResponse(HttpResponseBase):
    return HttpResponse()

render

def render(...):
    return HttpResponse(...)

redirect

def redirect(to, *args, permanent=False, **kwargs):
        redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect  # 三元表达式
        return redirect_class(resolve_url(to, *args, **kwargs))

视图函数返回json格式数据

将下列数据用json格式展示到网页

user_dict = {'name': 'jason老师', 'pwd': 123, 'hobby': ['read', 'run', 'music']}

json方法

def obj_json(request):
    json_str = json.dumps(user_dict, ensure_ascii=False)
    return HttpResponse(json_str)

JsonResponse方法

from django.http import JsonResponse
def obj_json(request):
    return JsonResponse(user_dict, json_dumps_params={'ensure_ascii':False}, safe=False)

'''序列化非字典类型的数据还需要指定safe参数为False'''

JsonResponse源码解析

from django.http import JsonResponse
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 = {}
        data = json.dumps(data, cls=encoder, **json_dumps_params)
        super().__init__(content=data, **kwargs)

from表单携带文件数据

form表单上传的数据中如果含有文件,那么需要做以下几件事。

第一:method属性值必须是post。

第二:enctype属性值必须修改为multipart/form-data,默认是application/x-www-form-urlencoded。

第三:后端需要使用request.FILES获取,然后就可以通过句点符和with open等查看和下载文件信息。

request补充方法

方法 说明
request.body 存放的是接收过来的最原始的二进制数据,request.POST、request.GET、request.FILES这些获取数据的方法其实都从body中获取数据并解析存放的
request.path 获取路径
request.path_info 获取路径
request.get_full_path() 获取路径并且还可以获取到路径后面携带的参数

FBV与CBV

FBV:基于函数的视图

def index(request):
    return HttpResponse()

path('index/', views.index)

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源码分析

源码分析入口

path('func/', views.MyView.as_view())

1.切入点:路由匹配

类名点属性as_view并且还加了括号
as_view可能是普通的静态方法
as_view也可能是绑定给类的方法

2.对象查找属性的顺序

先从对象自身开始、再从产生对象的类、之后是各个父类
MyView.as_view()
先从我们自己写的MyView中查找,没有再去父类Views中查找

3.CBV路由匹配本质:跟FBV是一致的

项目已启动就会执行as_view方法 查看源码返回了一个闭包函数名view
def as_view(cls):
    def view(cls):
      pass
    return view
path('func/', views.view)
# 函数名加括号执行优先级最高

4.路由匹配成功之后执行view函数(访问func触发view执行)

def view(...):
    obj = cls() # cls我们直接写的类,加括号产生一个自己写的类的对象
    return obj.dispatch(request, *args, **kwargs)
'''涉及到对象点名字 一定要确定对象是谁 再确定查找顺序'''

5.研究dispatch方法

def dispatch(...):
      # 利用getattr反射(通过字符串操作对象的属性和方法)
      #参数:obj自己写的类产生的对象,当前的请求方法。 handler就等于自己写的类里的请求方法
      handler = getattr(obj, request.method.lower())
      # 返回的时候加括号传承调用自己写的类里的请求方法
      return handler(request, *args, **kwargs)

ps:查看源码也可以修改,但是尽量不要这么做,很容易产生bug。

模板层

模板语法传值

django提供的模板语法只有两个符号:

{{}}:主要用于数据;{%%}:主要用于方法。

传值的两种方式

# 方式1:指名道姓的传,适用于数据量较少的情况,节省资源
return render(request, 'modal.html', {'name':name})
# 方式2:打包传值(关键字locals()),将整个局部名称空间中的名字全部传入,适用于数据量较多的情况,简单快捷
return render(request,'modal.html',locals())

模板语法传值的范围

数据类型 说明
基本数据类型 都可以直接传递使用
函数名 传递会自动加括号执行并将返回值展示到页面上,函数如果有参数不会执行也不会展示,模板语法不支持有参函数
类名 传递会自动加括号产生对象并展示到页面上
对象 直接传递使用(显示对象的地址,并且具备调用属性和方法的能力)
文件名 直接显示文件IO对象

django的模板语法在操作容器类型的时候只允许使用句点符

data1 = {'info':{'pro':[11, 22, 33, {'name':'jason','msg':'努力就有收获'}]}}
{{ data1.info.pro.3.msg }}  # 既可以点key也可以点索引  django内部自动识别

模板语法过滤器(类似于python内置函数)

<p>统计长度:{{ s|length }}</p>
<p>加法运算:{{ i|add:123 }}</p>、<p>加法运算:{{ s|add:'heihei' }}</p>
<p>日期转换:{{ s|date:'Y-m-d H:i:s' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>数据切片:{{ l|slice:'0:10' }}</p>
<p>字符截取(三个点算一个):{{ s1|truncatechars:6 }}</p>
<p>单词截取(空格):{{ s1|truncatewords:6 }}</p>

# 在前端使用 |safe
<p>语法转义:{{ script_tag|safe }}</p>  # safe:将后端写的代码可以在前端被识别被转换

# 在后端使用mark_safe
from django.utils.safestring import mark_safe
script_tag1 = '<script>alert(666)</script>'
res = mark_safe(script_tag1)

<p>{{ res }}</p>
ps:有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入

模板语法标签(类似于python流程控制)

在django模板语法中写标签的时候,只需要写关键字然后tab键就会自动补全。

1.if判断

{% if 条件 %}   # 条件一般是模板语法传过来的数据  直接写名字使用即可
    条件成立执行的代码
{% elif 条件1 %}
    条件1成立执行的代码
{% else %}
    条件都不成立执行的代码
{% endif %}

2.for循坏

{% for i in s %}
    {% if forloop.first %}
        <p>这是第一次哟~</p>
    {% elif forloop.last %}
        <p>这是最后一次!</p>
    {% else %}
        <p>{{ i }}</p>
    {% endif %}
    {% empty %}  # # empty 循环对象为空执行
        <p>你给我的是个空 怎么for循环呢</p>
{% endfor %}

forloop关键字:{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}
# counter0:从0开始计数;counter:从一开始计数;first': 是否是第一次循环;last是否是最后异常循环

补充:如果数据是字典,同样提供了keys、values、items方法。

a={'name':jason,'age':18}
{{ for i in a.keys}} 
 <p>{{ i }}</p> # name age 
{% endfor %}
{{ for i in a.values}} 
 <p>{{ i }}</p> # jason 18 
{% endfor %}
{{ for i in a.items}} 
 <p>{{ i }}</p> # ('name',jason) ('age',18)
{% endfor %}

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

如果想自定义,必须做以下三件事:

1.在应用下创建一个名为templatetags文件夹

2.在该文件夹创建任意名称的py文件

3.在该文件内编写自定义相关固定代码

from django.template import Library
register = Library()

自定义过滤器:只能接收两个参数

@register.filter(name='myfilter') # 括号内可以通过name给过滤器取别名
def my_add(a, b):
    return a + b

# 在html页面使用过滤器需要先导入创建的py文件模块
{% load mytag %}
{{ i|myfilter:1 }}

自定义标签函数:可以接收任意参数

@register.simple_tag(name='mt')
def func(a, b, c, d):
    return a + b + c + d

{% load mytag %}
{% mt 1 2 3 4 %}  # 参数之间空格隔开即可

自定义inclusion_tag

@register.inclusion_tag(filename='it.html')
def index(n):
    html = []
    for i in range(n):
        html.append('第%s页'%i)
    return locals()
#it.html里内容
<ul>
    {% for i in html %}
        <li>{{ i }}</li>
    {% endfor %}
</ul>
'''该方法需要先作用于一个局部html页面 之后将渲染的结果放到调用的位置 类似于封装了一个能够快速产生html代码的方法'''

{% load mytag %}
{% index 10 %}

模板的继承

类似于面向对象的继承:继承了某个页面就可以使用该页面上所有的资源。

如果我们想要继承获取一个页面的大部分只修改一部分代码,我们也可以用继承来实现。

母页面

# 先在母板中通过block划定将来可以被修改的区域(可以有多个)
{% block 名字 %}
    母板内容
{% endblock %}

子页面

{% extends 'html文件名' %} # html文件名是母页面的HTML文件名,继承了母页面

{% block 名字 %}  # 这里写的内容可以直接修改母页面里可以被修改的区域
    子板内容
{% endblock %}

'''子板中还可以使用母板的内容  {{ block.super }} '''

模板上最少应该有三个区域可以让子页面继承:css区域、内容区域、js区域。子页面就可以有自己独立的css、js、内容

{% block css %}
    css修改内容
{% endblock %}

{% block 名字 %}
    子板内容
{% endblock %}

{% block js %}
    js修改内容
{% endblock %}

子页面还可以重复使用父页面的内容

{{ block.super }}

模板的导入

类似于将html页面上的局部页面做成模块的形式,哪个地方想要直接导入即可展示。

使用方式

{% include 'menu.html' %}

注释语法补充

<!----> 是HTML的注释语法
{##}    是django模板语法的注释
"""
HTML的注释可以在前端浏览器页面上直接查看到
模板语法的注释只能在后端查看 前端浏览器查看不了
"""
posted @   空白o  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示