11_04、Django请求生命周期流程图、路由层、cbv源码

一、Django请求生命周期流程图

image-20200924175613811

二、路由层

1、路由文件

项目中url.py文件中,添加路由设置

urlpatterns = [
    url(r'^test/', views.test),
]
r'^test/'  # 正则表达式,匹配以test开头,以/结尾的字符,r是去掉转义符,保证斜杠只是斜杠字符,而不会发生转义
views.test # view.py文件中的test函数内存地址

注意:settings.py文件中的APPEND_SLASH控制斜杠自动匹配

APPEND_SLASH = True  # 控制斜杠自动匹配(默认)
APPEND_SLASH = False  # 取消斜杠自动匹配

2、有名分组和无名分组

1.什么是分组

有名分组和无名分组是正则分组的两种形式。

分组是通过括号把正则表达式括起来,特征是组内优先展示。

路由文件中的r'^test/'是一个正则表达式,所以也可以通过有名分组和无名分组的方式书写

2.为什么要用到分组

url中的前半部分(r'^test/'),是用户输入的网址后缀。

是为了给后半部分(views.test)这个函数名的内存地址匹配。

通过正则分组可以作为位置实参给函数传参

但是注意,有几个分组(参数),函数内就必须有相应的位置形参用于接收。

3、实例演示

有名分组:

# url.py文件
urlpatterns = [
    url(r'^test/(\d+)/(\a+)', views.test),
]
# view.py文件
def test(request, first, second):
    print(first)  # (\d+)匹配的内容
    print(second)  # (\a+)匹配的内容
    return render(request, 'test.html', locals())

无名分组:

# url.py文件
urlpatterns = [
    url(r'^test/(?P<year>\d+)/(?P<month>\a+)', views.test),  # 有名分组,给正则名称:year,month
]
# view.py文件
def test(request, first, second):
    print(first)  # (\d+)匹配的内容是关键字year
    print(second)  # (\a+)匹配的内容匹配的内容是关键字month
    return render(request, 'test.html', locals())

注意:如果参数太多,可以用*args,**kwargs接收

# view.py文件
def test(request, args, **kwargs):
    print(*args)  
    print(**kwargs) 
    return render(request, 'test.html', locals())

3、反向解析

1、起别名

针对过长匹配的url,我们可以用name给其重命名

urlpatterns = [
    url(r'^test/test1/test2/test3/', views.test, name='test'),  # 给r'^test/test1/test2/test3/'重命名为test
]

2、反向解析

反向解析就是通过name反向解析出原来的url

后端反向解析

# view.py文件
from django.shortcuts import reverse


def test(request):
    print(reverse('test'))  # /test/test1/test2/test3/
    return render(request, 'test.html', locals())

前端反向解析

# test.html文件

<body>
    <a href="{% url 'test' %}">前端反向解析</a>
</body>

无名分组前端反向解析

 

无名分组后端反向解析

 

 

有名分组前端反向解析

 

有名分组后端反向解析

 

 

4、路由分发

1、为什么要路由分发

 随着时间和用户的增多,我们的Django项目也会越来越大,那么毫无疑问我们的总路由文件也会也来越大

 

 

 这会导致项目非常难以维护,为此我们会把总路由分开到不同的应用下面去,这是受Django框架支持的。

Django支持每个应用下面有自己的:

# 1、url.py文件
# 2、static文件夹
# 3、templates文件夹

2、怎么路由分发

第一步:

把总路由复制到各个应用中,并修改

复制代码
# app02中的urls.py

from django.conf.urls import url
from django.contrib import admin
from app02 import views


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),

]
复制代码
复制代码
# app02中的urls.py

from django.conf.urls import url
from django.contrib import admin
from app03 import views


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),

]
复制代码

第二步:总路由分发(include)

方式一:

复制代码
"""
总路由文件urls.py
导入include
给分路由重命名
"""

from django.conf.urls import url, include
from django.contrib import admin
from app01 import views
from app02 import urls as app02_url
from app03 import urls as app03_url

# url.py文件
urlpatterns = [

    # 总路由分发
    url(r'^app02/', include(app02_url),),
    url(r'^app03/', include(app03_url),),

]
复制代码

方式二:

复制代码
"""
总路由文件urls.py
无需导入
"""
from django.conf.urls import url, include
from django.contrib import admin
from app01 import views

# url.py文件  

urlpatterns = [
    url(r'^app02/', include('app02.urls')),
    url(r'^app03/', include('app03.urls')),

]
复制代码

第三步:效果展示

查看app02

 

 查看app03

5、名称空间

我们再给路由起别名的时候,如果两个url命名为相同的名字

在根据别名反向解析的时候,默认解析的是最后一个

如果要精准解析,这里就要用到名称空间的知识了(namespace = '自定义名称空间名字')

# 总路由文件urls.py

urlpatterns = [

    url(r'^app02/', include('app02.urls', namespace='app02')),
    url(r'^app03/', include('app03.urls', namespace='app03')),

]

方向解析的时候

from django.shortcuts import render,HttpResponse,reverse

def index(request):
    print(reverse('app02:test'))
    return HttpResponse('app02:index')

三、虚拟环境

应用于多个多个项目,每个项目需要应用不同的模块、版本。

虚拟环境就是一个纯净版的python解释器,我们可以在这个虚拟环境上安装每个应用需要的插件

我们可以同时拥有多个虚拟环境

 

 

四、JsonResponse(json序列化)

json格式的数据用于跨语言传输,

编码就是把不用语言转成二进制,解码就是把二进制在转成各种不同的语言

序列化就是通过json通过把python的语言转换成json字符串,

反序列化就是通过json把json字符串转换成python格式

后端中的序列化和反序列化:

序列化:json.dumps

反序列化:json.loads

前端中的序列化和反序列化:

序列化:JSON.stringify()

反序列化:JSON.parse()

注意:

  前后端分离的项目,需要用到json格式的数据

  混合项目开发项目,用不到json格式的数据

 

django框架通过对json进一步封装,方便了我们实现数据的序列和反序列化

复制代码
from django.http import JsonResponse


def my_json(request):
    my_dict = {'username': '鲁迅', 'gender': 'male'}  # 字典类型
    my_list = [1, 2, 3]  # 非字典类型

    # res = json.dumps(my_dict, ensure_ascii=False)  # json转码
    # return HttpResponse(res)  # json序列化

    # return JsonResponse(my_json, json_dumps_params={'ensure_ascii': False})  # 字典类型的序列化
    return JsonResponse(my_list, safe=False)  # 非字典类型的序列化
复制代码

五、CBV的书写

CBV和FBV是一个概念的东西

FBV:function base views,顾名思义,基于视图的函数(views.py中的函数)

CBV:class base views,同理,基于视图的类(views.py中的类)

复制代码
'''views.py文件'''

# cbv必须继承View类
from django.views import View


class IndexClass(View):
    # 注意类中的方法名必须指定为八种请求方式中的一种,不能随意指定
    # 八种方式:get post push
    def get(self, request):
        return HttpResponse('get')

    def post(self,  request):
        return HttpResponse('post')
复制代码
'''urls.py'''

urlpatterns = [
    url(r'^my_cbv/', views.IndexClass.as_view()),
]

六、CBV的源码分析

 

 

七、form表单上传文件

之前我们学过get请求和post请求可以通过request.get和request.post接收请求数据

文件也有自己的接收方式:request.FILES

复制代码
'''views.py文件'''

def my_form(request):
    if request.method == 'POST':
        print(request.GET)  # get请求的对象request.GET,此处为<QueryDict: {}>
        print(request.POST)  # post请求的对象request.POST,此处为<QueryDict: {}>
        print(request.FILES)  # 文件对象在request.FILES,<MultiValueDict: {'myfile': [<InMemoryUploadedFile: 测试图片.png (image/png)>]}>
        # request.FILES只接收文件数据,其他请求一概不接收

        # 字典取值
        file_obj = request.FILES.get('myfile')
        print(file_obj.name)  # 文件的名称:微信截图_20220313203813.png

        # 上传文件
        with open(file_obj.name, 'wb') as f:
            # 上传文件的时候要一行一行读取,防止内存溢出
            for line in file_obj:
                f.write(line)
        # 上传的文件存放在项目的根目录
    return render(request, 'my_form.html')
复制代码
复制代码
    {# HTML文件 #}

    {#注意:form表单上传文件的两个必须条件method="post" enctype="multipart/form-data"#}
    <form action="" method="post" enctype="multipart/form-data">
        <p>
            上传文件:<input type="file" name="myfile">
        </p>
        <input type="submit" value="提交">
    </form>
复制代码
'''urls.py文件'''

urlpatterns = [
    url(r'^my_form/', views.my_form),  # 上传图片
]

注意:上传的文件存放在项目根目录 ,但是再次上传图片文件,会把原先上传的覆盖掉

我们可以通过导入随机数重命名,解决这个问题

复制代码
'''views.py文件'''

def my_form(request):
    if request.method == 'POST':
        print(request.GET)  # get请求的对象request.GET,此处为<QueryDict: {}>
        print(request.POST)  # post请求的对象request.POST,此处为<QueryDict: {}>
        print(request.FILES)  # 文件对象在request.FILES,<MultiValueDict: {'myfile': [<InMemoryUploadedFile: 测试图片.png (image/png)>]}>
        # request.FILES只接收文件数据,其他请求一概不接收

        # 字典取值
        file_obj = request.FILES.get('myfile')
        print(file_obj.name)  # 文件的名称:微信截图_20220313203813.png

        import uuid
        rend_str = uuid.uuid4()
        file_path = str(rend_str) + '.png'

        # 上传文件
        with open(file_path, 'wb') as f:
            # 上传文件的时候要一行一行读取,防止内存溢出
            for line in file_obj:
                f.write(line)
        # 上传的文件存放在项目的根目录
    return render(request, 'my_form.html')
复制代码

 

posted @   三三得九86  阅读(106)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示