Django 路由层

Django的下载与基本命令

  • 下载Django:pip3 install django==2.0.1
  • 建立一个django project: django-admin startproject luffy
  • 在mysite目录下建立应用:python manage.py startapp app01
  • 启动django项目:python manage.py runserver 8080 咱们访问:http://127.0.0.1:8080/时就能够看到:
  • python manage.py makemigrations
  • python manage.py migrate
  • python manage.py createsuperuser
  • 命令行查看django版本:python -m django --version

1、文件介绍

  • manage.py ----- Django项目里面的工具,经过它能够调用django shell和数据库等。
  • settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其余一些工做的变量。
  • urls.py ----- 负责把URL模式映射到应用程序。

静态文件

?
1
2
3
4
5
#在settings.py中:
STATIC_URL = '/static/'
STATICFILES_DIRS = (
     os.path.join(BASE_DIR, 'static' ),
)

路由

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行。html

1、简单的路由配置

  • 若要从URL 中捕获一个值,只须要在它周围放置一对圆括号。
  • 不须要添加一个前导的反斜杠,由于每一个URL 都有。例如,应该是^articles 而不是 ^/articles。
  • 每一个正则表达式前面的'r' 是可选的可是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不该该转义
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 在urls.py中:
from django.urls import path,re_path
from app01 import views
 
# 路由配置: 路径--------->视图函数
urlpatterns = [
     path( 'admin/' , admin.site.urls),
 
     #无名分组:捕获的值做为位置参数传递给视图函数
     re_path(r '^articles/([0-9]{4})/$' , views.year_archive), #year_archive(request,'2009')
     re_path(r '^articles/([0-9]{4})/([0-9]{2})/$' , views.month_archive), # month_archive(request,'2009','12')
     re_path(r '^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$' , views.article_detail), # month_archive(request,'2009','12','1'),# month_archive(request,'2009','12','13')
 
     #有名分组:捕获的值做为关键字参数传递给视图函数
     re_path(r '^articles/(?P<year>[0-9]{4})/$' , views.year_archive), # month_archive(request, year='2005')
     re_path(r '^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$' , views.month_archive), # month_archive(request, year='2005', month='03')
     re_path(r '^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$' , views.article_detail), # month_archive(request, year='2003', month='03', day='03')
 
]

2、分发

?
1
2
3
4
5
6
7
8
9
10
11
# 在urls.py中:
from django.urls import path, re_path, include
 
urlpatterns = [
     path( 'admin/' , admin.site.urls),
 
     # 分发
     re_path(r "^app01/" , include( "app01.urls" )),
     re_path(r "^app02/" , include( "app02.urls" )),
     re_path(r "^" , include( "app01.urls" )),
]

3、反向解析

得到URL 的最终形式,,对于不一样层级,Django 提供不一样的工具用于URL 反查:python

  • 在模板中:使用url 模板标签。
  • 在Python 代码中:使用from django.urls import reverse
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 在urls.py中:
from django.urls import path, re_path, include
from app01 import views
 
urlpatterns = [
     path( 'admin/' , admin.site.urls),
 
     # 反向解析
     path( 'login.html/' , views.login, name = "Log" ),
     re_path(r '^articles/([0-9]{4})/$' , views.year_archive, name = 'news-year-archive' ),
     re_path(r '^articles/(?P<year>[0-9]{4})/$' , views.year_archive, name = 'news-year' ),
 
]
 
# 在模板中:注意参数
"""
<form action="{% url 'Log' %}" method="post"></form>
 
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
<!--多个参数-->
<a href="{% url "n4" i1 i2 %}">编辑</a>
"""
 
# 在views.py中:
from django.urls import reverse
from django.shortcuts import render, HttpResponse, redirect
 
 
def redirect_to_year(request):
     # 无参
     url = reverse( 'Log' )
     print (url)
 
     # 有参
     year = 2006
     url88 = reverse( 'news-year-archive' , args = (year,))
     url99 = reverse( 'news-year' , kwargs = { 'year' : 2008 })
 
     return HttpResponse( 'OK' )

4、名称空间

命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不一样命名空间中的含义是互不相干的。咱们在开发项目时,会常用name属性反解出URL,当不当心在不一样的app的urls中定义相同的name时,可能会致使URL反解错误,为了不这种事情发生,引入了命名空间。git

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 在urls.py中:
from django.urls import path, re_path, include, url
 
urlpatterns = [
     path( 'admin/' , admin.site.urls),
 
     # 分发
     re_path(r "^app01/" , include( "app01.urls" )),
     re_path(r "^" , include( "app01.urls" )),
 
     # 两个应用中,URL 模式名字同样时:
     re_path(r "^app01/" , include(( "app01.urls" , "app01" ))),
     re_path(r "^app02/" , include(( "app02.urls" , "app02" ))),
 
]
# 模板中
{ % url 'app01:index' % }
{ % url 'app02:index' pk = item. id % }  带参数的
 
# app01中的urls.py
from django.urls import path, re_path
from app01 import views
 
urlpatterns = [
     re_path( "index/" , views.index, name = "index" )
]
 
# app02中的urls.py
from django.urls import path, re_path
from app02 import views
 
urlpatterns = [
     re_path( "index/" , views.index, name = "index" )
]
 
# app01中的views.py
from django.shortcuts import render, HttpResponse,redirect
from django.urls import reverse
 
 
def index(reqeust):
     return redirect(reverse( "app01:index" ))
 
 
# app02中的views.py
from django.shortcuts import render, HttpResponse
from django.urls import reverse
 
 
def index(reqeust):
     return redirect(reverse( "app02:index" ))

一、注意

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 'Specifying a namespace in include() without providing an app_name '
"""
方法1:在proj/urls.py中修改
"""
urlpatterns = [
     # url(r'^rbac/', include('rbac.urls', namespace='rbac')),
     url(r '^rbac/' , include(( 'rbac.urls' , 'rbac' ), namespace = 'rbac' )),
]
 
"""
方法2:在rbac/urls.py中 添加 app_name='rbac'
"""
app_name = 'rbac'
urlpatterns = [
     url(r '^role/list/$' , role.role_list, name = 'role_list' ),  # rbac:role_list
     ...
]
 
"""
'ForeignKey' object has no attribute 'rel'
"""
self .remote_field = rel
 
# return SearchGroupRow(title, field_object.rel.model.objects.filter(**db_condition), self, request.GET)
return SearchGroupRow(title, field_object.remote_field.model.objects. filter ( * * db_condition), self , request.GET)

5、django2.0版的path

一、基本实例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 在urls.py中:
from django.urls import path, re_path
from app01 import views
urlpatterns = [
     re_path( 'articles/(?P<year>[0-9]{4})/' , views.year_archive),
     re_path( 'article/(?P<article_id>[a-zA-Z0-9]+)/detail/' , views.detail_view),
     re_path( 'articles/(?P<article_id>[a-zA-Z0-9]+)/edit/' , views.edit_view),
     re_path( 'articles/(?P<article_id>[a-zA-Z0-9]+)/delete/' , views.delete_view),
]
"""
1.函数 year_archive 中year参数是字符串类型的
2.三个路由中article_id都是一样的正则表达式,可是你须要写三遍,当以后article_id规则改变后,须要同时修改三处代码,
在Django2.0中,可使用 path 解决以上的两个问题。
"""
urlpatterns = [
     path( 'articles/2003/' , views.special_case_2003),
     path( 'articles/<int:year>/' , views.year_archive),
     path( 'articles/<int:year>/<int:month>/' , views.month_archive),
     path( 'articles/<int:year>/<int:month>/<slug>/' , views.article_detail),
]

二、基本规则

  • 使用尖括号(<>)从url中捕获值。
  • 捕获值中能够包含一个转化器类型(converter type),好比使用 捕获一个整数变量。若果没有转化器,将匹配任何字符串,固然也包括了 / 字符。
  • 无需添加前导斜杠。

三、path转化器

Django默认支持如下5个转化器:正则表达式

  • str,匹配除了路径分隔符(/)以外的非空字符串,这是默认的形式
  • int,匹配正整数,包含0。
  • slug,匹配字母、数字以及横杠、下划线组成的字符串。
  • uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
  • path,匹配任何非空字符串,包含了路径分隔符

四、注册自定义转化器

对于一些复杂或者复用的须要,能够定义本身的转化器。转化器是一个类或接口,它的要求有三点:shell

  • regex 类属性,字符串类型
  • to_python(self, value) 方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。
  • to_url(self, value) 方法,和 to_python 相反,value是一个具体的Python变量值,返回其字符串,一般用于url反向引用。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# urls.py:
from django.urls import register_converter, path
from app01 import yearconvert,views
 
#使用register_converter 将其注册到URL配置中:
register_converter(yearconvert.FourDigitYearConverter, 'yyyy' )
 
urlpatterns = [
     path( 'articles/<yyyy:year>/' , views.year_archive),
]
 
#app01.yearconvert.py:
class FourDigitYearConverter:
     regex = '[0-9]{4}'  #规则
     def to_python( self , value):
         return int (value) # 在这转换了类型
     def to_url( self , value):
         return '%04d' % value
 
#app01.views.py:
from django.shortcuts import render,HttpResponse,redirect
def year_archive(request,year):
     print (year, type (year))
     return HttpResponse( 'ok' )

MVC与MTV模型

1、MVC

Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式链接在一块儿,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求,其示意图以下所示:数据库

2、MTV

Django的MTV模式本质上和MVC是同样的,也是为了各组件间保持松耦合关系,只是定义上有些许不一样,Django的MTV分别是:django

  • M 表明模型(Model): 负责业务对象和数据库的关系映射(ORM)。
  • T 表明模板 (Template):负责如何把页面展现给用户(html)。
  • V 表明视图(View): 负责业务逻辑,并在适当时候调用Model和Template。
  • 除了以上三层以外,还须要一个URL分发器,它的做用是将一个个URL的页面请求分发给不一样的View处理,View再调用相应的Model和Template,MTV的响应模式以下所示:

相关文章
相关标签/搜索