1. 程式人生 > 實用技巧 >Django1.x與Django2.0常用功能區別

Django1.x與Django2.0常用功能區別

Django1.x與Django2.0常用功能區別

目錄

一、路由的區別

1、Django1中的url

  1. 使用url
  2. url寫的是正則,模糊匹配
  3. 使用(\d+)
    (?P<name>\d+)實現分組,從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.Django2特有的url

url規則:

  1. 使用path
  2. path寫的是絕對字串,請求地址必須與路由地址完全匹配
  3. 使用尖括號 <> 從url中獲取引數值
  4. 可以使用轉換器指定引數型別,例如: int:age 捕獲一個整數引數age,
    若果沒有轉化器,將匹配任何字串,也包括路徑分隔符 /
  5. 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

3、自定義轉換器

步驟:

  1. 自定義一個類

  2. 類中必須有:類屬性regex,to_python方法,to_url方法

    • regex:類屬性,字串型別

    • to_python(self, value)方法:value是由類屬性 regex 所匹配到的字串,返回具體的Python變數值,以供Django傳遞到對應的檢視函式中。

    • 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):
        # url反向解析
        return '%2s' % value

# 在主路由 urls.py 下匯入,生成轉換器
from django.urls import register_converter

register_converter(Date,'date')   # 註冊轉換器

path('full-year/<date:full_year>/',views.full_year, name="full_year")

4、Django2的url相容了Django1的寫法

  • Django2中的re_path與Django中的url用法完全相同
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。

  • 語法:namespace:url_name'

例如:

# 專案中的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了。

2、Django2

1)基本使用

# 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),
]

2)某些字首一致的情況

# 這種方法可以用來去除URLconf中的冗餘,其中某個模式字首被重複使用。例如,考慮這個URLconf:

from django.urls import path
from . import views

urlpatterns = [
    path('<page_slug>-<page_id>/history/', views.history),
    path('<page_slug>-<page_id>/edit/', views.edit),
    path('<page_slug>-<page_id>/discuss/', views.discuss),
    path('<page_slug>-<page_id>/permissions/', views.permissions),
]
我們可以改進它,通過只宣告共同的路徑字首一次並將後面的部分分組:

from django.urls import include, path
from . import views

urlpatterns = [
    path('<page_slug>-<page_id>/', include([
        path('history/', views.history),
        path('edit/', views.edit),
        path('discuss/', views.discuss),
        path('permissions/', views.permissions),
    ])),
]

3)反向解析

from django.urls import path
from . import views

urlpatterns = [
    path('articles/<int:year>/', views.year_archive, name='archive'),
]

根據這種設計,對應於年度歸檔檔案的URL是 /articles/<nnnn>/


你可以使用以下方法在模板程式碼中獲取這些:
<a href="{% url 'archive' 2012 %}">2012 Archive</a>


或者在Python程式碼中:

from django.http import HttpResponseRedirect
from django.urls import reverse

def redirect_to_year(request):
    year = 2006
    return HttpResponseRedirect(reverse('archive', args=(year,)))

4)名稱空間

注意:如果直接使用name做反向解析(即使用了include),也不需要設定app_name,但是使用namespace,需要設定app_name

# 1.專案的urls
from django.urls import path, include


urlpatterns = [
    path('myapp/', include('MyApp.urls', namespace='my')),
    path('yourapp/', include('YourApp.urls', namespace='you')),
]

# 2.1 MyApp.urls.py
from django.urls import path
from MyApp import views

app_name = 'myxxx'  # 在各個APP級別的urls中設定app_name

urlpatterns = [
    path('index/', views.index, name="index"),
    path('home/', views.home, name="home"),
]

# 2.2 MyApp.Views.py
from django.shortcuts import render, redirect, HttpResponse
from django.urls import reverse


def index(request):
    return HttpResponse("MyApp-index")


def home(request):
    print("home")
    return redirect(reverse('my:index'))
    # return redirect(reverse('myxxx:index'))  # 也可以使用app_name

# 3.1 YourApp.urls.py
from django.urls import path
from YourApp import views

app_name = 'yourxxx'  # 在各個APP級別的urls中設定app_name

urlpatterns = [
    path('index/', views.index, name="index"),
    path('hello/', views.hello, name="hello"),
]


# 3.2 YourApp.Views.py
from django.shortcuts import render, redirect, HttpResponse
from django.urls import reverse


def index(request):
    return HttpResponse("YourApp-index")


def hello(request):
    print("hello")
    return redirect(reverse('you:index'))
    # return redirect(reverse('yourxxx:index'))  # 也可以使用app_name

# 4. 在模板中使用
<a href="{% url 'my:index' %}">myapp-index</a>  # 可以寫namespace
<a href="{% url 'yourxxx:index' %}">your-index</a>  # 可以寫app_name

三、其他的一些區別

1、ORM外來鍵

Django1.0:hbook = models.ForeignKey('BookInfo')
Django2.0:hbook = models.ForeignKey('BookInfo', on_delete=models.CASCADE)

轉載於:https://www.cnblogs.com/Zzbj/p/11150041.html