django框架之路由层 视图层......

Django 框架结构

urlspy    路由层
views.py  视图层
templates   模板层
models.py   模型层

 

路由层

数据处理结果request,是由wsgiref完成

1. 路由匹配

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', views.home),  # 网站首页路由
    url(r'test/$', views.test),  # 以test/结尾
    url(r'testadd/$', views.testadd),  # 以testadd/结尾
    url(r'', views.error)   # 网站不存在页面,该路由存在,网页将不会自动加/重定向
]

url('正则表达式',“视图函数内存地址”)

url(r'^index.html',views.index)

url(r'^index/\d+.html',views.index)
url(r'^index/[0-9]{4}/',views.index)

第一个参数是正则表达式,匹配规则按照从上往下依次匹配,匹配到一个后立即执行对应的函数,不再继续往下匹配

路由过多的时候,可能在它之前就有路由匹配上,目标函数将不会被执行,一可以换前后位置,二换新的路由

PS:路由匹配到的数据默认都是字符串形式

 

1)分组

无名分组:将加括号的正则表达式匹配到的内容,当做位置参数自动传递给对应的视图函数
有名分组:将加括号的正则表达式匹配到的内容,当做关键字参数自动传递给对应的视图函数

注意:无名分组和有名分组不支持混合使用!!!

  但是支持用一类型多个分组匹配

urlpatterns = [
    url(r'^admin/', admin.site.urls),
  url(r'^admin/([0-9]{4})/', admin.site.urls),  # 无名分组, url(r
'^test/\d+/', views.test), # 匹配一个或多个数字,只要有数字访问不受影响 url(r'^test/(\d+)/', views.test1), # 无名分组,会将\d+当做位置参数传递给函数 url(r'^test/(\d+)/(\d+)/', views.test11), # 无名分组多个 url(r'^test/(?P<year>\d+)/', views.test2), # 有名分组,会将\d+当做关键字参数传递给函数 url(r'^test/(?P<year>\d+)/(?P<xx>\d+)/', views.test22) # 有名分组多个 ]
def test(request):
    return HttpResponse('test')


def test1(request, xx):
    print(xx)
    return HttpResponse('test1')


def test11(request, xx, yy):  # 形参可以任意表示,但数量相等
    print(xx)
    print(yy)
    return HttpResponse('test11')


def test2(request, year):
    print(year)
    return HttpResponse('test2')


def test22(request, xx, year):  # 形参必须与路由相同,位置任意
    print('xx:', xx)
    print('year:', year)
    return HttpResponse('test22')

 

2)反向解析

视图层根据名字动态获取该别名所对应的能够匹配url的路径 from django.shortcuts import reverse

可以给每一个路由与视图函数对应关系起一个别名
这个名字能够唯一标识出对应的路径
注意:这个名字不能重复是唯一的 

本质:获取到能够访问名字所对应的视图函数

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/$', views.index, name='index'),  # 路由与视图函数的关系取别名 index
    url(r'^index1/$', views.index1, name='index1'),  # 别名 index1
    url(r'^test3/(\d+)/', views.test3, name='test3'),  # 别名 test3
   url(r'^test4/(\d+)/(\d+)/(\d+)/', views.test4, name='test4'), # 别名 test4
]
from django.shortcuts import render,HttpResponse,reverse


def index(request):
    print('url:', reverse('index'))
    return render(request, 'index.html')


def index1(request):
    print(reverse('test3', args=(1,)))  # test3 需要一个无名分组参数,不传参报错
    return render(request, 'index1.html')


def test3(request, xx):
    print('xx:', xx)
    print('url:', reverse('index1'))
    return HttpResponse('test3')
def test4(request, *args):     
  print(reverse('test4', args=args)) # /test4/599/288/246/
  return HttpResponse(*args) # 599 ??
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>

<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>
<a href="{% url 'index' %}"></a>


</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<a href="{% url 'test3' 10 %}"></a>
<a href="{% url 'test3' 10 %}"></a>
<a href="{% url 'test3' 10 %}"></a>
<a href="{% url 'test3' 10 %}"></a>
<a href="{% url 'test3' 10 %}"></a>
<a href="{% url 'index1' %}"></a>
<a href="{% url 'index1' %}"></a>
<a href="{% url 'index1' %}"></a>
<a href="{% url 'index1' %}"></a>

</body>
</html>
index1.html
# 反向解析(根据名字动态获取到对应路径)
    url(r'^index6668888/$',views.index,name='index')
前端使用
    {% url '别名' %}
后端使用
    from django.shortcuts import reverse
    reverse('index')

# 无名分组反向解析
    url(r'^test/(\d+)/',views.test,name='list')
后端使用
    reverse('list',args=(10,))
前端使用
    {% url 'list' user_obj.pk %}

# 有名分组反向解析
后端使用
    reverse('list',args=(10,))    # 后端有名分组和无名分组都可以用这种形式
    reverse('list',kwargs={'year':10})    # 下面这个了解即可
前端使用
    {% url 'list' user_obj.pk %}    # 前端有名分组和无名分组都可以用这种形式
    {% url 'list' xxx=user_obj.pk %} # 下面这个了解即可  


# 总结:针对有名分组与无名分组的反向解析统一采用一种格式即可
  后端 reverse(
'list',args=(10,)) # 这里的数字通常都是数据的主键值
  前端 {
% url 'list' user_obj.pk %}

实例

展示数据:
user_list = models.User.objects.all()

url(r'^edit/(\d+)', views.edit, name='edit')
前端模板语法
     {% for user_obj in user_list %}
        <a href='edit/{{ user_obj.pk }}/'></a>
{% endfor %}
增加编辑按钮: 视图函数
from django.shortcuts import reverse def edit(request, edit_id): url = reverse('edit', args=(edit_id,)) 模板 {% url 'edit' edit_id %}


3)路由分发

django每一个app下面都可以有自己的urls.py路由层,templates文件夹,static静态文件夹
项目名下urls.py(总路由)不再做路由与视图函数的匹配工作,而是做一个中转

项目名下urls.py:路由分发千万不要$结尾

from django.conf.urls import include
from app01 import urls as app01_urls 
from app02 import urls as app02_urls
url(r
'^app01/', include(app01_urls)),
url(r'^app02/', include(app02_urls)),
url(r'^app03/', include('app03.urls'))

在应用下新建urls.py文件,在该文件内写路由与视图函数的对应关系即可

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^index/', views.index)
]

4)名称空间

当多个app中给路由与视图起别名重名的情况,使用名称空间避免反向解析不准的情况

不使用名称空间,可以在起别名的时候加上一些具有唯一标识的前缀

项目urls.py
url(r'^app01/',include(app01_urls,namespace='app01')),
url(r'^app02/',include(app02_urls,namespace='app02'))

app01.urls.py
    from django.conf.urls import url
    from app01 import views
    urlpatterns = [
        url(r'^index/',views.index,name='index')
    ]

app02.urls.py
    from django.conf.urls import url
    from app02 import views
    urlpatterns = [
        url(r'^index/',views.index,name='index')
    ]

app01.views.py
reverse('app01:index')

app02.views.py
reverse('app02:index')

 

5)伪静态网页

搜索优化seo:Search Engine Optimization,利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名

url(r'^index.html',views.index,name='app01_index')
url(r'^index/\d+.html',views.index,name='app01_index')

 

6)虚拟环境

每一个项目都有属于自己的python环境,避免导入多余的模块造成资源的浪费;

不同的项目配置不同的python解释器,配置需要用到的模块、版本

7)django1.0与django2.0

区别1:django2.0里面的path第一个参数不支持正则,你写什么就匹配,100%精准匹配

区别2:django2.0里面的re_path对应着django1.0里面的url

虽然django2.0里面的path不支持正则表达式,但是它提供五个默认的转换器

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

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

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

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

path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)

自定义转换器:

1.正则表达式

2.类 :写两个方法 to_python & to_url

3.注册:起一个名字

url(r'^index/<str:id>',views.index) 
url(r'^index/<xxx:id>',views.index)


from
django.urls import register_converter # 自定义转换器 class FourDigitYearConverter: regex = '[0-9]{4}' def to_python(self, value): return int(value) def to_url(self, value): return '%04d' % value # 占四位,不够用0填满,超了则就按超了的位数来! register_converter(FourDigitYearConverter, 'yyyy')

 

视图层

1. FBV与CBV

后端业务逻辑FBV与CBV完成

FBV:function base views,在视图里使用函数处理请求

CBV:class base views,在视图里使用类处理请求

无论是FBV还是CBV,路由层都是路由对应视图函数内存地址

# CBV 路由层
url(r'^login/', views.MyCls.as_view()) # .的左边容器类型 # CBV 视图层
from django.views import View
from django.shortcuts import HttpResponse, render

class MyCls(View): def get(self, request): return render(request, 'index.html') def post(self, request): return HttpResponse('post')

 

2. JsonResponse对象

是HttpRespon的子类,第一个参数是一个字典类型,

返回json的字符串,

json_dumps_params参数是一个字典,它将调用json.dumps()方法,'ensure_ascii'值为False时,传入的中文不会被编码为十六进制码

from django.http import JsonResponse
import json

json.dumps(dict, ensure_ascii=False)
def index9(request): dic = {'name': 'Tom的哥哥', 'age': 18} return JsonResponse(dic, json_dumps_params={'ensure_ascii': False}) 输出: {"name": "Tom的哥哥", "age": 18}

 


3. 文件上传

前端需注意:

1. method 指定成 post(默认get)

2. enctype 改为 formdata格式(默认urlencoded)

后端注意点:

1. 配置文件settings.py中,注释掉csrfmiddleware中间键

2. 通过request.FILES 获取上传的post文件数据

file_obj = request.FILES.get('my_file')
    with open(file_obj.name, 'wb') as f:
        for line in file_obj.chunks():
            f.write(line)

 

 

 

posted @ 2019-06-10 22:57  zhoyong  阅读(274)  评论(0编辑  收藏  举报