Django之路由层、视图层、模板层介绍

一、Django请求生命周期

Django之路由层、视图层、模板层介绍_第1张图片

1.路由层urls.py

Django 1.11版本 URLConf官方文档

1.1 urls.py配置基本格式

from django.conf.urls import url

urlpatterns = [
     url(正则表达式, views视图函数,参数,别名),
]

1.11.x版本默认

from django.conf.urls import url

urlpatterns = [
    url(r'^admin/', admin.site.urls),
url(r'^test/$', views.test),
] 
# 获取到用户输入的url后,根据正则匹配是否对应
# http://127.0.0.1:8000/test 请求的时候实际是请求了2次,第一次请求是按照浏览器输入的进行请求,但是没有匹配到,第二次请求浏览器会自动在末尾加一个/之后进行匹配,如果还匹配不上直接报错
# 注意事项
1 urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
2 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
3 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
4 每个正则表达式前面的'r' 是可选的但是建议加上。

 

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # url(r'test/[0-9]{4}/$', views.test),
    # 无名分组:会将分组内的结果 当做位置参数自动传递给后面的视图函数views.py
    url(r'test/([0-9]{4})/$', views.test),
    # url(r'^test/(\d+)/$',views.test),
    # 有名分组:会将分组内的结果 当做关键字参数自动传递给后面的视图函数
    url(r'^testadd/(?P[0-9]{4})/$',views.testadd),
]
# 无名分组:http://127.0.0.1:8000/test/3333/,视图函数加参数后可以访问,如果不加会提示test() takes 1 positional argument but 2 were given
# 有名分组

 1.2 反向解析

  根据别名动态解析出可以匹配上视图函数之前的url的一个结果(注意:在起别名的时候,一定要保证 所有的别名都不能重复,必须是唯一的)

# urls.py
    url(r'^testxxx/',views.test,name='t')
    url(r'^test/(\d+)/$',views.test,name='ttt'),

# 前端
    没有正则表达式的反向解析
    {% url 't' %}
    无名分组反向解析
    有名分组同上
   有正则表达式的反向解析
   {% url 'ttt' 1 %} # 数字通常是数据库中字典的pk值
# 后端 from django.shortcuts import render,HttpResponse,redirect,reverse 没有正则表达式的反向解析 reverse('t')
   无名分组反向解析 reverse(
'ttt',args=(1,)) #有正则表达式的反向解析函数视图views.py 有名分组同上 # urls.py中使用别名后,testxxx无论怎么变,浏览器中路径也会自动变化,动态解析到前端

有名分组和无名分组能否混合使用?
---有名无名不能混合使用!!!

1.3 页面伪静态

# 伪静态
    让一个动态页面伪装成一个看似数据已经写死了的静态页面,其实是经过了视图函数处理,动态渲染的页面
    好处:让搜索引擎加大对你这个页面的收藏力度,当别人搜索你这个页面相关内容,提高优先展示概率(花钱最好)
    加大seo查询

# 例如:在urls.py中将路由设置成,视图函数views.py中还是不变:return HttpResponse("index.html")
url(r'^index.html$',views.index),
例如:10982293.html https://www.cnblogs.com/Dominic-Ji/articles/10982293.html

 1.4 django版本区别1.x与2.x

1.X
    路由里面用的是url()
2.X
    路由里面的用的是path()
    url第一个参数放的是正则表达式
    而你的path第一个参数写什么就是什么,不支持正则
    如果你还想使用第一个参数是正则的方法
    django2.X版本中有一个叫re_path()
    ps:2.x中re_path就等价于1.x中的url
        
    # 虽然path不支持正则表达式,但是它提供了五种转换器(了解)

1.5 路由分发

    当一个django项目下面有多个app的情况下,总的urls.py中路由与视图函数的对应关系太多 不便于管理
这个时候就可以再每个app下创建自己的urls.py,总的urls.py不再做对应关系,而只是做分发任务 每个app下都可以有自己的urls.py static文件夹 templates模板文件,也就意味着 每个app都可以被独立的开发出来 而不需要讨论交互
#  路由分发:根据前缀,去对应的目录下查找路由

# 总路由下urls.py配置
# 重名的使用别名
from django.conf.urls import url,include
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)),
]

# 应用app01下的路由
from django.conf.urls import url
from app01 import views

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

# app01下的视图函数views.py
from django.shortcuts import render,HttpResponse,redirect

def urlindex(request):
    return HttpResponse("app01下的index")

# 应用app02下的路由
from app02 import views

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

# app02下的视图函数views.py
from django.shortcuts import render,HttpResponse,redirect

def urlindex(request):
    return HttpResponse("app02下的urlindex")

# 访问app01下的链接:http://127.0.0.1:8000/app01/urlindex
# 访问app02下的链接:http://127.0.0.1:8000/app02/urlindex
# 都可以显示对应的提示

# 如果2个app下起了相同的名字,那么反向解析不支持自动查找应用前缀,需要了解名称空间的概念
# app01
urlpatterns = [
    url(r'^urlindex',views.urlindex,name='aaa')
]
# app02
urlpatterns = [
    url(r'^urlindex',views.urlindex,name='aaa')
]
# views.py中都打印下print('aaa')
# 访问app01和app02的urlindex后端打印的都是一样的

# 第一种方法:
# 反向解析的时候可以在name='aaa'中添加前缀解决
# 例如:name='app01_aaa'

# 第二种方法:
# 名称空间(了解既可):在分发的时候再起一个名字
# 总路由urls.py中
urlpatterns = [
    url(r'^app01/',include(app01_urls,namespace='app01')),
    url(r'^app02/',include(app02_urls,namespace='app02')),
]

#app01中的路由urls.py
urlpatterns = [
    url(r'^urlindex',views.urlindex,name='aaa')
]
# app01的views.py
def urlindex(request):
    print(reverse('app01:aaa'))
    return HttpResponse("app01下的index")
# app02的路由
urlpatterns = [
    url(r'^urlindex',views.urlindex,name='aaa')
]
# app02的views.py
def urlindex(request):
    print(reverse('app02:aaa'))
    return HttpResponse("app02下的urlindex")

# 然后分别访问就正常了

# 使用importlib方法:


2. 视图层

2.1 JsonResponse

# views.py
import json
def index(request):
    d = {'name':'simon','password':'123','hobby':'读书'}
    # 前端不支持字典,需要转成json格式
    return HttpResponse(json.dumps(d,ensure_ascii=False))
# 前端页面显示:http://127.0.0.1:8000/index/
{"name": "simon", "password": "123", "hobby": "读书"}

# 第二种方式:
from django.http import JsonResponse
def index(request):
    d = {'name':'simon','password':'123','hobby':'读书'}
    # 前端不支持字典,需要转成json格式
    # return HttpResponse(json.dumps(d))
    return JsonResponse(d)

# JsonResponse直接转换成json格式
# 前端没显示中文,可以通过JsonResponse源代码来看方法
# return JsonResponse(d,json_dumps_params={'ensure_ascii':False})

2.2 FBV与CBV

FBV function based views

CBV class based views

# views.py
from django.views import View
class MyLogin(View):
    def get(self,request):
        return HttpResponse("Get")

    def post(self,request):
        return HttpResponse("Post")

# urls.py中如何添加路径?
# CBV路由配置
url(r'^login/',views.MyLogin.as_view()),

# 可以在前端home.html写一个页面测试post提交方式
"/login/" method="post"> "submit">
# 可以看到我们访问login直接返回Get # 访问home.html点击提交就会跳到login页面显示post
# 可以看到get请求来走get,post请求走post

3.模板层

 模板语法--模板传值

# 模板语法 url.py
url(r'^demo/',views.demo),
# views.py
def demo(request):
    i = 1
    f = 1.11
    s = 'hello'
    # s = []
    l = [1,2,3,4,5,6,7,8,9]
    t = (1,2,3,4)
    d = {'name':'simon','password':'123'}
    se = {1,2,3,4}
    # 通过字典传值方式
    # return render(request,'demo.html',{'xxx':[1,2,3,4]})
    
    def foo():
        print("foo")
        return "0000000oooooooooo"

    class Demo(object):
        def index(self):
            return 'index'

        @classmethod
        def login(cls):
            return 'cls'

        @staticmethod
        def reg():
            return 'reg'

    obj = Demo()
    return render(request,'demo.html',locals())  # locals 会将所在名称空间中的所有名字全部传递给前端页面

# 前端页面
# 第一种传值方式
return render(request,'demo.html',{'xxx':[1,2,3,4]})
# 前端使用
{{ xxx }}

# 第二种传值方式
# locals 会将所在名称空间中的所有名字全部传递给前端页面
return render(request,'demo.html',locals())
# 前端页面需要将所有定义的:i f s等使用双大括号括起来显示
# 如果是函数传到前端显示

{{ foo }} 如果是函数名,传递到前端会自动加()调用,将调用后的结果展示到前端页面

#如果是类 {#

{{ obj.index }} 只要是方法 都会自动加括号调用

#}

# 获取列表字典中某一个值
前端{{ l.0 }} or {{ d.name }}

 3.1.过滤器

# 后端3中demo类中直接定义n和i
    import datetime
    ctime = datetime.datetime.now()
    sss = 'sadfasf sdfasf fasdfsadf sdfa'

# 前端:
{{i|add:19}}  # 结果:20
{{n|filesizeformat}}  # n的值进行转化成文件大小M、G等
{{ ctime|date:'Y-m-d' }}  # 日期获取
{{ sss|truncatechars:20 }} # 截断一部分...来省略(20包含3个点)
{{ sss|truncatewords:2 }}  # 截断,只识别空格
#后端
def demo(request):
    h = "

我是h1标签

" s1 = "" # 后端转义views.py from django.utils.safestring import mark_safe s2 = "

我是h2标签

" s2 = mark_safe(s2) # 这样前端就不需要用safe了 # safe告诉前端我这个代码是安全的,可以渲染 # 前端转义 {{ h|safe }} {{ s1 }} # 这个如果加safe,前端就会死循环 {{ s2 }}

3.2 标签

# 后端
def demo(request):
    l = [1,2,3,4,5,6,7,8,9]
    s3 = [1,2]
    s4 =[None,1]

# 模板语法的if判断    
# 前端demo.html
{% if s3 %}
    

有值{{ s3 }}

# 返回结果就是这个了 {% else %}

这个东西是空的

{% endif %} {% if s4.0 %}

有值{{ s4 }}

{% elif s4.1 %}

没值

{% else %}

这个东西是空的

{% endif %} # 就算值取不到也不会报错 {% for foo in l %} {# # foo为每次列表循环的元素,first为第一个值,last为最后一个值,中间可以#} {% if forloop.first %}

first...

{% elif forloop.last %}

这是last

{% else %}

继续啊~~~

{% endif %} {% empty %}

是空的,不能循环

{% endfor %}

3.3 模板的继承与导入

# 模板的继承
# 在你想做成模板的页面上 添加block块儿 来标识其他用户可以占用的区域
{% extends 'tmp.html' %}

    {% block content %}
                
        {% endblock %}
# 先在模板中划定区域,之后子板利用block就能够找到模板中可以被使用的区域

# 通常情况下 模板中最少有三个区域
css
content
js
ps:模板中的block块儿越多 页面的可扩展性越高
# 模板的导入
将一块html页面作为模块的方式 导入使用
{% include 'goodpage.html' %}
将goodpage.html页面内容直接导入到该语句的位置
# 模板的继承与导入



    
    Title
    
    
    



{% block content %}

Hello, world!

...

Learn more

{% endblock %}
# login.html 模板的导入 {% extends 'tmp.html' %} {% block content %}

登录

username:

password:

{% endblock %} # reg.html模板的导入与继承 {% extends 'tmp.html' %} {% block content %} {# 模板的导入#} {% include 'good.html' %}

注册

username:

password:

{% endblock %}

 

转载于:https://www.cnblogs.com/yangmeichong/p/11411360.html

你可能感兴趣的:(Django之路由层、视图层、模板层介绍)