Python学习第120天(Django1和2之间的区别)
昨天实操了Django之后,发现课程中讲到的Django1和我目前使用的Django2之间还是存在很多区别的,所以今天就多浪费了一些流量,加上自己试了一些结果,暂时总结一下之间的区别吧。
一、先说一下Django中url分发的问题,这个2中明显更为优秀,但是我还不怎么会用,教学视频也没有讲到。
1.Django1中的url
from django.conf.urls import url # 使用url关键字 urlpatterns = [ url('article-(\d+).html',views.article), url('article-(?P<article_id>\d+).html',views.article) ] # url请求地址为:http://127.0.0.1:8000/article-1.html Django1的url支持正则匹配: 'article-(\d+).html':使用正则表达式的分组匹配来获取URL中的参数,并以位置参数形式传递给视图article。 'article-(?P<article_id>\d+).html':使用正则表达式的分组命名匹配来获取URL中的参数,并以关键字参数的形式传递给视图article。 分组命名正则表达式组的语法是:(?P<name>pattern),其中name是组的名称(视图中的关键字参数必须跟组名一致),pattern是正则表达式。
2.Django2中的url
(1)2中所特有的url写法
url书写规则:
1.path写的是绝对字符串,请求地址必须与路由地址完全匹配
2.使用尖括号 <> 从url中获取参数值
3.可以使用转换器指定参数类型,例如: <int:age> 捕获一个整数参数age,若果没有转化器,将匹配任何字符串,也包括路径分隔符 /
4.path拥有5个转换器:
str:匹配除路径分隔符 / 外的字符串
int:匹配自然数
slug:匹配字母,数字,横杠及下划线组成的字符串
uuid:匹配uuid形式的数据
path:匹配任何字符串,包括路径分隔符 /
from django.urls import path # 使用path关键字 urlpatterns = [ path('article-<int:article_id>.html',views.article), ] # url请求地址为:http://127.0.0.1:8000/article-1.html
自定义转换器:
步骤:
1.自定义一个类
2.类中必须有:类属性regex,to_python方法,to_url方法
3.regex:类属性,字符串类型
4.to_python(self, value)方法:value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。
5.to_url(self, value)方法:和 to_python 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。
class Date: regex = '^0?[1-9]$|^1[0-2]$' def to_python(self, value): # 可以写你的逻辑,对匹配到的字符串进行处理 value = '2019/' + value return value def to_url(self, value): return '%2s' % value # 在主路由下导入,生成转换器 from django.urls import register_converter register_converter(Date,'date') path('full-year/<date:full_year>/',views.full_year, name="full_year")
2.Django2的url兼容了Django1的写法
from django.urls import re_path 这里的re_path的用法跟Django1的url用法视完全一样的,匹配正则。 urlpatterns = [ path('articles/2003/', views.special_case_2003), # Django2的写法 re_path('articles/(?P<year>[0-9]{4})/', views.year_archive), # 兼容Django1的写法 re_path('articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/', views.month_archive), re_path('articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[^/]+)/', views.article_detail), ]
后面可以暂时按照课程中设置的要求,先按照兼容模式书写
二、关于路由分发的include
1.关于Django1
1.include其他的URLconfs(二级路由系统)
创建两个app,每个app都创建一个urls.py # 项目的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'^app01/', include(app01_urls)), url(r'^app02/', include(app02_urls)), ] # app01的urls.py from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^book/$', views.book_list), url(r'^book/(?P<yyyy>[0-9]{4})/$', views.book), url(r'^blog/$', views.blog), url(r'^blog/(?P<num>\d+)/$', views.blog), ] # app02的urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/$', views.index), url(r'^home/$', views.home), ] 解析:在浏览器输入http://127.0.0.1:8000/app02/home/ 首先会拿着app02/home/去项目的urls中匹配,找到url(r'^app02/', include(app02_urls)), 看到include,就拿着home/去app02的urls中匹配,找到url(r'^home/$', views.home),就访问home页面。
这个是比较熟悉的模式
2.命名URL和URL反向解析
在最终的路由那里设置name属性,给这个路由设置别名,
然后在视图函数那里导入from django.urls import reverse,
在需要解析地址的地方使用reverse(别名),就可以解析出这个url,
且无论路由本身的地址如何改变,只要使用reverse(别名),一样能解析出url地址
例如:
# 项目的urls.py from django.conf.urls import url, include from app02 import urls as app02_urls urlpatterns = [ # 二级路由系统 url(r'^app02/', include(app02_urls)), ] # app02的urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^login/$', views.login), url(r'^index/$', views.index, name='myindex'), ] # views.py from django.shortcuts import render, redirect, HttpResponse from django.urls import reverse # 导入reverse反向解析出地址 def login(request): if request.method == 'POST': username = request.POST.get('username') pwd = request.POST.get('pwd') ret = UserInfo.objects.filter(username=username, pwd=pwd) if ret: return redirect(reverse('myindex')) # reverse反向解析出url地址:/app02/index/ return render(request, 'login.html') def index(request): return HttpResponse('index') 解析:在浏览器输入http://127.0.0.1:8000/app02/login/,进入登录界面, 登录成功后,redirect(reverse('myindex')),reverse会根据别名myindex自动解析出index的具体路径(http://127.0.0.1:8000/app02/index/), 而且无论index的具体路由怎么改变,reverse('myindex')总是能解析出具体的url。 注意:当url需要参数时: 1.如果index需要传位置参数: urlpatterns = [ url(r'^index/(\d+)/$', views.index, name='myindex'), ]
return redirect(reverse('myindex', args=('2018',))) 2.如果index需要传关键字参数: urlpatterns = [ url(r'^index/(?P<year>\d+)/$', views.index, name='myindex'), ]
return redirect(reverse('myindex', kwargs={'year': '2019'})) # 在HTML模板中使用 无参数:<a href="{% url 'myindex' %}">myindex</a> 有参数:<a href="{% url 'myindex' '2018' %}">myindex</a>
3.命名空间模式
如果不同的APP使用了相同的URL反转名称,那么reverse怎么解析?
使用命名空间模式(namespace)可以解决这个问题,即不同的APP使用相同的URL名称,URL的命名空间模式也可以让你唯一反转命名的URL。
例如:
项目中的urls.py from django.conf.urls import url, include urlpatterns = [ 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/(?P<year>\d+)/$', views.index, name='myindex'), ] # app02中的urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/(?P<year>\d+)/$', views.index, name='myindex'), ] 现在,两个app中url的别名重复了,反转URL的时候就可以通过命名空间的名称得到我当前的URL。 语法: '命名空间名称:URL名称' # 在HTML模板中使用: <a href="{% url 'app01:myindex' '2018' %}">app01 myindex</a> <a href="{% url 'app02:myindex' '2019' %}">app02 myindex</a> # 在views中的函数中使用 v = reverse('app01:myindex', kwargs={'year':2018}) v = reverse('app02:myindex', kwargs={'year':2019}) 这样即使app中URL的命名相同,我也可以反转得到正确的URL了。
Django2部分
暂时只看了基本使用方法,后学还有对应的明天看时间吧,自己要去学习纪检知识。
In settings/urls/main.py from django.urls import include, path urlpatterns = [ path('<username>/blog/', include('foo.urls.blog')), ] # In foo/urls/blog.py from django.urls import path from . import views urlpatterns = [ path('', views.blog.index), path('archive/', views.blog.archive), ]
今天内容有点多,得好好吸收啊。