Django其四

一、路由层

  1、分组与反向解析:

    ①路由层:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^xxx/(d+)/', views.xxx, name='ooo'),  # 无名分组
    url(r'^xxx_p/(?P<ttt>d+)', views.xxx_p, name='ooo_p'),  # 有名分组
    url(r'^yyy/(d+)/', views.yyy)
]

    ②视图层:

def xxx(request, ttt):
    print(reverse('ooo', args=(ttt,)))
    # ===> /xxx/123/
    return HttpResponse('来了老弟')


def xxx_p(request, ttt):
    print(reverse('ooo_p', args=(ttt,)))  # 可以用跟无名分组一样的写法
    print(reverse('ooo_p', kwargs={'ttt': ttt}))  # 有名分组的专用写法
    # ===> /xxx_p/123/
    # ===> /xxx_p/123/
    return HttpResponse('来了老弟_p')


def yyy(request, ddd):
    return render(request, 'yyy.html', {'hhh': ddd})

    ③模板层:

<a href="{% url 'ooo' hhh %}" class="btn btn-info">点我跳转xxx</a>  <!--无名分组-->
<a href="{% url 'ooo_p' ttt=hhh %}" class="btn btn-info">点我跳转xxx_p</a>  <!--有名分组-->
<a href="{% url 'ooo_p' hhh %}" class="btn btn-info">点我跳转xxx_p</a>  <!--有名分组也可以跟无名分组写法一样-->

  2、路由分发:

    ①Django项目的每一个app都可以用自己独立的templates文件夹,urls.py文件,views.py文件,以此来实现一个Django项目分工开发,每个人或每组人只需要开发自己分属的app,最后再由组长将所有app拷贝到一个空的Django项目中,然后在配置文件中注册这些app,再通过路由分发的机制将所有app整合起来。

    ②当一个Django项目的路由特别多的时候,若都写在总urls.py中的话,会使得代码变得非常冗余不便维护,此时也可以利用路由分发的机制来简化总路由的结构,如此一来,总路由不再直接显示具体路由与视图函数的对应关系,而是体现为分发结构,一个url进入Django后台后,会先经过总路由分发,再交给对应app内的路由层进一步处理。

    ③总路由层的写法一:

from app01 import urls as app01_urls
from app02 import urls as app02_urls

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/', include(app01_urls)),
    url(r'^app02/', include(app02_urls))
]

    ④总路由层的写法二:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/', include('app01.urls')),
    url(r'^app02/', include('app02.urls'))
]

  3、名称空间:当多个app出现了相同的别名,反解析是无法区分具体属于哪个app的,此时需要借助名称空间的机制。

    ①总路由层:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/', include('app01.urls', namespace='app01')),
    url(r'^app02/', include('app02.urls', namespace='app02'))
]

    ②app01的路由层:

urlpatterns = [
    url('^xxx/', views.xxx, name='ooo'),
    url('^yyy/', views.yyy)
]

    ③app01的视图层:

def xxx(request):
    print(reverse('app01:ooo'))
    # ===> /app01/xxx/
    return HttpResponse('app01的xxx')


def yyy(request):
    return render(request, 'yyy.html')

    ④app01的模板层:

<a href="{% url 'app01:ooo' %}" class="btn btn-info">点我跳转app01的xxx</a>

    ⑤常用的做法是,各个app内的别名可以都加上app名为前缀来规避别名冲突,简化代码,例如,在总路由层不声明子路由层的名称空间的情况下,子路由层可以如此书写:

urlpatterns = [
    url('^xxx/', views.xxx, name='app01_ooo')
]

  4、伪静态页面:

    ①静态页面:页面文件的代码是明确且固定,所以页面也是固定的。

    ②伪静态页面:将一个动态页面伪装成静态页面。

    ③搜索引擎本身就是一个大型的爬虫程序,所以,伪装的目的:

      a、为了提高本网站的seo查询力度。

      b、为了增加搜索引擎收藏本网站的概率。

      c、提示并无***用,效果微乎其微,花钱才是硬道理。

    ④实现伪装:

urlpatterns = [
    url(r'^xxx.html',views.xxx)  # 在路由后面加上.html即可
]

  5、虚拟环境:

    ①简述:将现有解释器的初始纯净状态提取拷贝出来建立成一个独立的解释器环境,这样的环境就叫做虚拟环境,初始的虚拟环境中没有任何第三方模块,要用什么再装什么。

    ②一个虚拟环境也就是一个独立的解释器环境,所占空间与原解释器相差无几,所以如果有很多虚拟环境则会占用过多的硬盘空间。

    ③对于一些常用的或通用的第三方模块,可以保存于一个requirements.txt文件中,里面集成了这些模块包括版本号在内的信息,当新建一个虚拟环境的时候,若需要全部或大部分用到其中的模块,通过该文件一键安装即可。

  6、Django不同版本之间的区别:

    ①路由层:

      1.0+:默认使用url方法,使用正则匹配。

      2.0+&3.0+:

        a、默认使用path方法,使用绝对匹配,可以另用re_path方法,用法与url方法一致,也可以用url方法,但是如此就无法体现是在用2.0+或3.0+的版本。

        b、path方法有五种转换器:path('xxx/<int:id>/', xxx)---将第二个路由里面的内容先转成整型然后以关键字的形式传递给后面的视图函数,除了int,还有其他声明代表不同含义:

          ---str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式。

          ---int,匹配正整数,包含0。

          ---slug,匹配字母、数字以及横杠、下划线组成的字符串。

          ---uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。

          ---path,匹配任何非空字符串,包含了路径分隔符</>,不能用<?>。

        c、除了有默认的五个转换器之外 还支持自定义转换器。

    ②模型层:

      1.0+:外键默认都是级联更新和级联删除的。

      2.0+&3.0+:需要手动配置。

models.ForeignKey(to='Classes', on_delete=models.CASCADE,on_update=models.CASCADE )

二、视图层

  1、入门三件套:

    ①HttpResponse:返回字符串。

    ②render:返回html页面,并且在返回给浏览器之前还可以给html文件传值。

    ③redirect:重定向,其他网站url或同站路由。

    ④三者的的底层都是返回的HttpResponse对象。

    ③简单模仿render内部原理:

from django.template import Template,Context

res = Template('<h1>{{ user }}</h1>')
con = Context({'user':{'username':'jason','password':123}})
ret = res.render(con)return HttpResponse(ret)

  2、JsonResponse对象:

    ①序列化字典:

def show_json(request):
    t_dict = {'name': '李雷', 'age': 18, 'gender': 'male'}
    t_list = [1, 2, 3, 4, 5]
    # 返回JsonResponse对象,自动序列化为json格式,要关闭默认的ascii编码
    return JsonResponse(t_dict, json_dumps_params={'ensure_ascii': False})

    ②序列化其他类型:

def show_json(request):
    t_dict = {'name': '李雷', 'age': 18, 'gender': 'male'}
    t_list = [1, 2, 3, 4, 5]
    # 默认只能序列化字典,其他类型需要关闭safe参数
    return JsonResponse(t_list, safe=False)

  3、form表单上传的文件在后端的操作:

    ①method必须指定成post。

    ②enctype必须换成multipart/form-data。

    ③实例:

def get_file(request):
    if request.method == 'POST':
        # 获取文件数据
        file_data = request.FILES
        # 获取文件对象
        file_obj = file_data.get('img_file')
        with open(r'上传的图片.jpg', mode='wb')as f:
            # 加上chunks方法强调按行读取
            for line in file_obj.chunks():
                f.write(line)
    return render(request, 'upload.html')
<form action="" method="post" enctype="multipart/form-data">
    <p><input type="file" name="img_file"></p>
    <p><input type="submit" value="提交上传"></p>
</form>

  4、request对象方法小结:

request.method
request.POST
request.GET
request.FILES
request.body
request.path  # 获取url,但不会携带?后面参数
request.path_info  # 同上
request.get_full_path()  # 获取完整url
原文地址:https://www.cnblogs.com/caoyu080202201/p/12977313.html