django路由层
0.上节关键命令
创建项目 django-admin startproject 项目名称
创建应用 python manage.py startapp app名称
启动项目 python manage.py runserver IP PORT
1.url配置(URLconf)
功能:URLconf就像是django所支撑网站的目录,它其实建立起了url与视图函数的映射关系。通过这种方式告诉django,客户端发来的某个url调用哪一段逻辑代码对应执行
例如当用户访问/views/时,去调用相关的视图函数,这个视图函数存在于views.Py中
django和URL配置背后的哲学遵循松耦合原则,松耦合是一个重要的保证互换性的软件开发方法
url下的path是django2.0的语法,re_path属于1.0的语法,目前2.0也兼容这种语法,导入即可
url部分(记住了,一个url模式就是一个正则表达式)
urlpatterns = [ # 用户在url中输入127.0.0.1:8000/articles/2003/,可以直接调用函数 url(r'^articles/2003/$', views.special_case_2003), # 利用优先匹配,获取用户输入年月 url("^articles/(\d{4})/(\d{2})/$", views.article_month), # 什么都不写也会默认访问这一个index视图,这个也很重要 url(r'^$', views.index), ]
# 正则表达式字符串的开头字母“r”。 它告诉Python这是个原始字符串,不需要处理里面的反斜杠(转义字符)
# 当为网站根目录实现一个视图,你需要使用URL模式`` ‘^$’`` , 它代表一个空字符串
views部分
from django.shortcuts import render,HttpResponse,redirect from django.urls import reverse # Create your views here. def special_case_2003(request): return HttpResponse('get it') def article_month(request,year,month): print(year, type(year)) print(month, type(month)) return HttpResponse(year + ":" + month) def index(request): return HttpResponse('首页默认显示')
注:
若要在url中捕获一个值,只需要在他周围加上一对圆括号,如上例
不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles
而不是 ^/articles
。
每个正则表达式前面的'r' 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义
1.2有名分组
上面简单配置只是通过简单配置来捕获URL中的值,并通过位置参数传给视图,可以使用命名的正则表达式组来捕获URL 中的值并以关键字参数传递给视图。
就是给分组起个名字,通过使用关键字传参
url部分
from django.conf.urls import url from app import views # 有名分组 urlpatterns = [ url("^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$",views.article_day) # article_year(request,year=2000,month=12,day=12) ]
views部分
from django.shortcuts import render,HttpResponse,redirect from django.urls import reverse # 这里形参无论怎么放置都无所谓了 def article_day(request,month,day,year): return HttpResponse(year + "-" + month + "-" + day)
1.3 分发
首先需要引入一个函数include(看urls.py下的注释),当你存在多个app的时候,彼此互不影响,各自从各自的app中去查找,好处是用于解耦
include的背后是一种即插即用的思想
from django.urls import path,include urlpatterns = [ path('app01/',include("app01.urls")), path('app02/',include("app02.urls")), ]
1.4 反向解析,别名,命名空间
url下的名字由于业务需求领导要求变更,这意味用到该路径的地方都需要更改,模板中用到这个名字的地方都需要改,一个项目中可能包含几十个模板文件,此时意味着维护起来代价相当高,此时则引入了反向解析这种语法,通过使用别名name来提高代码的灵活性。
案例一(不带参数的url):
url部分(不管怎么变动,我们只需更改这里的url部分即可,大大减少了工作量)
from django.urls import path from app import views urlpatterns = [ path("login/", views.login, name="log_in"), path("index/", views.index, name="index"), ]
视图部分
from django.shortcuts import render,HttpResponse,redirect from django.urls import reverse # 导入反向解析的一个函数 def login(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') if user=='bob' and pwd=='123': # 登录成功后直接跳转到首页index,即重定向, # 不过下面这样写就又被写死了,如果url中一改这里也需要改动 # 现在也需要通过在url下使用别名 # return redirect("index") # 硬编码 url = reverse("index") # 反向解析 print("url", url) # url /index/ return redirect(url) # 这步就是重定向 return render(request,"login.html") def index(request): return HttpResponse('跳转成功')
模板部分(login.html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {#注意这里内容必须要放在form表单里,否则无法实现跳转#} <form {% url 'log_in' %} method="post"> 姓名:<input type="text" name="user"> 密码:<input type="password" name="pwd"> <input type="submit"> </form> </body> </html>
案例二(携带参数的url):
对于携带参数的url,这时候我们别名的语法如下:
urls.py
from django.conf.urls import url from . import views urlpatterns = [ #... url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'), #... ]
# 某一年nnnn对应的归档的URL是/articles/nnnn/
我们在模板中获取:
<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>
在试图函数中:
from django.urls import reverse from django.http import HttpResponseRedirect def redirect_to_year(request): # ... year = 2006 return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
注:
思路其实通过以不变(别名name)应万变
在模板文件中:
{% url ‘别名’ %}
在视图函数中:
from django.urls import reverse
url=reverse(别名)
名称空间(namespace)
url别名name我们可以随意起名,但是如果在两个不同的app,在各自的urlconf中为某一条url取了相同的name,这就会带来麻烦。因此才引入了我们的名称空间
URL命名空间可以保证反查到唯一的URL,即使不同的app使用相同的URL名称也不受影响
urls.py
from django.conf.urls import include, url urlpatterns = [ url(r'^author-polls/', include('polls.urls', namespace='author-polls')), url(r'^publisher-polls/', include('polls.urls', namespace='publisher-polls')), ]
2.静态文件配置问题
这里提出这个静态文件配置,主要是由于我们url解析一些HTML标签的时候,当中存在jQuery或者bootstrap事件,这些都需要我们提前导入特定的功能包才能使用。当然使用网络提供的路径也可以使用,但是如果网络环境发生变化,极有可能导致我们的HTML某些事件无法加载,因此才提出了静态文件配制问题
首先我们需要在manage.py同级目录下创建一个文件夹(一般就以static命名),然后将下载好的jQuery或者bootstrap配置文件放到该文件夹内
接着我们需要在setting文件下进行相关路径配置:
STATIC_URL = '/static/' #这个配置就相当于配置的别名,如果这里的名字修改了就按照这里的名字去导入 STATICFILES_DIRS = [ os.path.join(BASE_DIR,"static") # 找到static绝对路径 ]
现在基本配置就完成了,如果在标签中使用,直接导入该相对路径即可
<link rel = "stysheet",href= "/static/index.css/"> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">