1、視圖
視圖一般都寫在app的views.py中。并且視圖的第一個參數永遠都是request(一個HttpRequest)對象。這個對象存儲了請求過來的所有資訊,包括攜帶的參數以及一些頭部資訊等。在視圖中,一般是完成邏輯相關的操作。比如這個請求是添加一篇部落格,那麼可以通過request來接收到這些資料,然後存儲到資料庫中,最後再把執行的結果傳回給浏覽器。視圖函數的傳回結果必須是HttpResponseBase對象或者子類的對象。
視圖檔案:book/views.py
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
# django架構中寫視圖函數,必須要傳參request
def book(request):
return HttpResponse("圖書首頁") # 傳回值必須是 HttpResponse包裹住的類型
# django架構中寫視圖函數,必須要傳參request
def index(request):
return HttpResponse("hello world") # 傳回值必須是 HttpResponse包裹住的類型
定義路由檔案:項目名稱 /urls.py, 該路由檔案與其他檔案互相關聯的原因在
frist_django/settings.py
檔案中的
ROOT_URLCONF = 'frist_django.urls'
設定,frist_django是項目app名稱。
"""frist_django URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.http import HttpResponse
from book.views import book # 從其他app子產品中導入定義的路由方法
from book.views import index
urlpatterns = [
path('admin/', admin.site.urls), # django預設路由前面有/,不需要添加
path('', index), # 路由為/,綁定的方法是book子產品中views.py的index方法
path('book/', book), # 路由為book/,綁定的方法是book子產品中views.py的index方法
]
2、URL映射
視圖寫完後,要與URL進行映射,也即使用者在浏覽器中輸入什麼url的時候可以請求到這個視圖函數。在使用者輸入了某個url,請求到我們的網站的時候,django會從項目的urls.py檔案中尋找對應的視圖。在urls.py檔案中有一個urlpatterns變量,以後django就會從這個變量中讀取所有的比對規則。比對規則需要使用django.urls.path函數進行包裹,這個函數會根據傳入的參數傳回URLPattern或者是URLResolver的對象。
from django.contrib import admin
from django.urls import path
from book import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/',views.book_list)
]
3、URL中添加參數
建立新的Django項目
# 首先先進入虛拟環境下
cd /d E:\ENV\Django項目\2-課
# 建立django項目,名稱為django_url
django-admin startproject django_url
# 進入
cd django_url\
# 建立新的app子產品,名稱為book
python manage.py startapp book
有時候,url中包含了一些參數需要動态調整。比如簡書某篇文章的詳情頁的url,是https://www.jianshu.com/p/a5aab9c4978e後面的a5aab9c4978e就是這篇文章的id,那麼簡書的文章詳情頁面的url就可以寫成https://www.jianshu.com/p/,其中id就是文章的id。那麼如何在django中實作這種需求呢。這時候我們可以在path函數中,使用尖括号的形式來定義一個參數。比如我現在想要擷取一本書籍的詳細資訊,那麼應該在url中指定這個參數。(後面的a5aab9c4978e就是這篇文章的id,是為了安全考慮,防止SQL注入等手段;還有就是隐藏網站中的真實文章數量等功能)
1. 第一種url傳參方式
視圖檔案:book/views.py
from django.shortcuts import render
from django.http import HttpResponse
def book(request):
return HttpResponse("圖書首頁")
def book_detail(request, book_id, cate_id):
return HttpResponse("圖書詳情,id為%s,分類id%s" % (book_id, cate_id))
定義路由檔案:項目名稱 /urls.py
from django.contrib import admin
from django.urls import path
from book import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/', views.book),
path('book/<book_id>/<cate_id>', views.book_detail), # <book_id>必須與views.book_detail方法中的參數名稱相同
]
使用反斜線 / 隔開傳參參數方式,實作的路由效果:
2. 第二種url傳參方式
視圖檔案:book/views.py
from django.shortcuts import render
from django.http import HttpResponse
def book_list(request):
print(type(request)) # 類<class 'django.core.handlers.wsgi.WSGIRequest'>
book_id = request.GET.get('id') # 從urls.py傳輸過來的參數id,GET是request類中的方法,request.GET傳回的是字典,get擷取字典中的參數
return HttpResponse("圖書清單%s" % book_id)
定義路由檔案:項目名稱 /urls.py
from django.contrib import admin
from django.urls import path
from book import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book_list/', views.book_list), # 關鍵字傳參,不需要在路由中寫參數
]
關鍵字傳參,以? 号隔開傳參參數,不需要在路由中寫參數,實作的路由效果:
def book_list(request):
print(type(request)) # 類<class 'django.core.handlers.wsgi.WSGIRequest'>
book_id = request.GET.get('id') # 從urls.py傳輸過來的參數id,GET是request類中的方法,request.GET傳回的是字典,get擷取字典中的參數
c_id = request.GET.get('cid')
return HttpResponse("圖書清單%s, 圖書類别是%s" % (book_id, c_id))
多個傳參以&号隔開,根據鍵值對的參數來顯示
4、URL子產品化
URL中包含另外一個urls子產品:
在我們的項目中,不可能隻有一個app,如果把所有的app的views中的視圖都放在urls.py中進行映射,肯定會讓代碼顯得非常亂。是以django給我們提供了一個方法,可以在app内部包含自己的url比對規則,而在項目的urls.py中再統一包含這個app的urls。使用這個技術需要借助include函數。
定義路由檔案:項目名稱 /urls.py
from django.contrib import admin
from django.urls import path, include # include是url子產品化
urlpatterns = [
path('admin/', admin.site.urls),
# path('book/', views.book),
# path('book/<book_id>/<cate_id>', views.book_detail), # <book_id>必須與views.book_detail方法中的參數名稱相同
# path('book_list/', views.book_list), # 關鍵字傳參,不需要在路由中寫參數
# url子產品化,定義book子產品的字首路由,關聯book子產品下的urls.py檔案
path("book/", include("book.urls"))
]
book子產品app檔案下的路由檔案:book/urls.py
# -*- encoding: utf-8 -*-
"""
@File : urls.py
@Time : 2020/6/17 15:54
@Author : chen
book子產品app檔案下的路由檔案:book/urls.py
"""
from django.urls import path
from . import views # 引用目前檔案夾下的views.py檔案
# 此時的路由是book子產品下定義的,需要被整體項目下的urls.py檔案包含,而且路由字首是需要在django_url/urls.py檔案中定義
urlpatterns = [
path('', views.book),
path('book/<book_id>/<cate_id>', views.book_detail), # <book_id>必須與views.book_detail方法中的參數名稱相同
path('book_list/', views.book_list), # 關鍵字傳參,不需要在路由中寫參數
]
在urls.py檔案中把所有的和book這個app相關的url都移動到app/urls.py中了,django_first/urls.py中,通過include函數包含book.urls,以後在請求book相關的url的時候都需要加一個book的字首。
實作效果如下:
5、Django内置轉換器
from django.urls import converters
UUID:https://www.cnblogs.com/franknihao/p/7307224.html
from django.urls import path
from . import views # 引用目前檔案夾下的views.py檔案
from django.urls import converters
# 此時的路由是book子產品下定義的,需要被整體項目下的urls.py檔案包含,而且路由字首是需要在django_url/urls.py檔案中定義
urlpatterns = [
path('', views.book),
# 需要限制book_id和cate_id的資料類型,采用int類型資料
path('book/<int:book_id>/<int:cate_id>', views.book_detail), # <book_id>必須與views.book_detail方法中的參數名稱相同
path('book_list/', views.book_list), # 關鍵字傳參,不需要在路由中寫參數
]
6、url命名與反轉
-
1.為什麼需要URL命名
因為在項目開發的過程中URL位址可能經常變動,如果寫死會經常去修改
- 2.如何給一個URL指定名稱
-
3.應用命名空間
在多個app之間可能産生同名的URL,這時候為了避免這種情況,可以使用命名空間來加以區分。在urls.py中添加app_name即可。
執行個體如下:
視圖檔案:front/views.py
from django.shortcuts import render, redirect,reverse # 重定向
from django.http import HttpResponse
def front_index(request):
# 傳參
username = request.GET.get('username') # 傳參username,模拟傳遞使用者名
if username:
return HttpResponse("前台首頁") # 模拟使用者登入後,轉到首頁界面
else: # 使用者未登陸的時候,需要重定向到登入界面
# 重定向
# return redirect('login/') # 位址與front/urls.py檔案中的路由位址要綁定
return redirect(reverse('front:login')) # 通過路由的name來進行反轉,查找到定義的路由"signin/",front:是限制該路由的應用命名空間名稱
def front_login(request):
return HttpResponse("前台登入界面")
注意:代碼中的front:是限制該路由的應用命名空間名稱,防止不同app子產品命名路由相同,通路出現重定義,限制路由通路,該命名從urls.py檔案中傳入。
定義前台路由檔案:front/urls.py
# -*- encoding: utf-8 -*-
"""
@File : urls.py
@Time : 2020/6/17 16:56
@Author : chen
定義前台路由檔案:front/urls.py
"""
from django.urls import path
from . import views
# 應用命名空間
app_name = "front"
urlpatterns = [
path("", views.front_index, name="index"),
path("signin/", views.front_login, name="login"), # 路由名稱signin/,如果後期項目需要修改路由,隻需修改這裡的路由位址,其他的都可以不用修改了
]
7、應用命名空間和執行個體命名空間
一個app,可以建立多個執行個體。可以使用多個URL映射同一個App。在做反轉的時候,如果使用應用命名空間,就會發生混淆,為了避免這個問題,可以使用執行個體命名空間,執行個體命名空間使用,namespace=‘執行個體命名空間’。
django_url/urls.py ,定義執行個體命名空間
from django.contrib import admin
from django.urls import path, include # include是url子產品化
# from book import views
urlpatterns = [
path('admin/', admin.site.urls),
# path('book/', views.book),
# path('book/<book_id>/<cate_id>', views.book_detail), # <book_id>必須與views.book_detail方法中的參數名稱相同
# path('book_list/', views.book_list), # 關鍵字傳參,不需要在路由中寫參數
# url子產品化,定義book子產品的字首路由,關聯book子產品下的urls.py檔案
path("book/", include("book.urls")),
path("cms/", include("cms.urls")),
path("", include("front.urls")), # 前台界面直接通路
path("cms1/", include("cms.urls", namespace='cms1')), # 執行個體命名空間
path("cms2/", include("cms.urls", namespace='cms2')), # 執行個體命名空間
]
cms/views.py, 顯示目前通路的執行個體命名空間名稱
from django.shortcuts import render
from django.http import HttpResponse
def cms_index(request):
current_namespace = request.resolver_match.namespace # 擷取目前通路的執行個體命名空間名稱
print(current_namespace)
return HttpResponse("背景首頁")
def cms_login(request):
return HttpResponse("背景登入界面")
8、URL反轉傳遞參數
如果這個url中需要傳遞參數,那麼可以通過kwargs來傳遞參數。
因為django中的reverse反轉url的時候不區分GET請求和POST請求,是以不能在反轉的時候添加查詢字元串的參數。如果想要添加查詢字元串的參數,隻能手動的添加。
login_url = reverse("front:singin") + "?name=xxx"
return redirect(login_url)
兩種反轉傳遞參數方式:
front/views.py
from django.shortcuts import render, redirect,reverse # 重定向
from django.http import HttpResponse
def front_index(request):
# 傳參
username = request.GET.get('username') # 傳參username,模拟傳遞使用者名
if username:
return HttpResponse("前台首頁") # 模拟使用者登入後,轉到首頁界面
else: # 使用者未登陸的時候,需要重定向到登入界面
# 重定向
# return redirect('login/') # 位址與front/urls.py檔案中的路由位址要綁定
# return redirect(reverse('front:login')) # 通過路由的name來進行反轉,查找到定義的路由"signin/",front:是限制該路由的應用命名空間名稱
# 第一種傳參:url反轉重定向傳參,關鍵字傳參
# return redirect(reverse('front:article', kwargs={"article_id": 3}))
# 第二種傳參:url反轉重定向傳參,字元串拼接傳參
return redirect(reverse('front:login') + "?name = 詳情資訊")
def front_login(request):
name = request.GET.get('name')
return HttpResponse("前台登入界面% s" % name) # 這種選擇字元拼接傳參
def front_article(request, article_id):
return HttpResponse("前台登入界面 %s" % article_id) # 這種選擇關鍵字傳參
定義前台路由檔案:front/urls.py
# -*- encoding: utf-8 -*-
"""
@File : urls.py
@Time : 2020/6/17 16:56
@Author : chen
定義前台路由檔案:front/urls.py
"""
from django.urls import path
from . import views
# 應用命名空間
app_name = "front"
urlpatterns = [
path("", views.front_index, name="index"),
path("signin/", views.front_login, name="login"), # 路由名稱signin/,如果後期項目需要修改路由,隻需修改這裡的路由位址,其他的都可以不用修改了
path("article/<article_id>", views.front_article, name="article"), # 定義路由
]
兩種傳參方式的選擇不同,效果如下: