Django框架——基礎之視圖系統(View.py)


Django框架之View.py(視圖文件)

1. 視圖簡介

視圖層是Django處理請求的核心代碼層,我們大多數Python代碼都集中在這一層面。

它對外接收用戶請求,對內調度模型層和模版層,統合數據庫和前端,最后根據業務邏輯,將處理好的數據,與前端結合,返回給用戶。視圖層是真正的后端,是Python工程師的‘主營業務’。

視圖就是每個創建的APP中的的view.py文件夾。我們處理數據的那些業務邏輯,就都存放(編輯)在這里。

Django的視圖層包含下面一些主要內容:

  1. URL路由
  2. 視圖函數
  3. 快捷方式
  4. 裝飾器
  5. 請求與響應
  6. 類視圖
  7. 文件上傳
  8. CSV/PDF生成
  9. 內置中間件

注意:視圖層應該包含視圖文件(view.py)路由文件(urls.py)兩個系統組成。

  

一個最新建的Django APP ,新建的APP名稱為(app001)如下:

 

1.1 一個簡單的視圖

下面是一個以HTML文檔的形式返回當前日期和時間的視圖:
復制代碼
from django.http import HttpResponse
from django.shortcuts import HttpResponse
import datetime def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
復制代碼

讓我們來逐行解釋下上面的代碼:

  • 首先,我們從 django.http(或者django.shorcuts)模塊導入了HttpResponse類,以及Python的datetime庫。

索引上面的兩個from引入語句的功能是一樣的,只需要其中一條就可以了!!!!!

  • 接着,我們定義了current_datetime函數。它就是視圖函數

  • 每個視圖函數都使用接收到的HttpRequest對象作為第一個參數,並且通常稱之為request

  • 注意,視圖函數的名稱並不重要;不需要用一個統一的命名方式來命名,以便讓Django識別它。我們將其命名為current_datetime,是因為這個名稱能夠比較准確地反映出它實現的功能(唯一性)。

  • 這個視圖會返回一個HttpResponse對象,其中包含生成的響應(HTML頁面或者一個字符串)。

  • 每個視圖函數都負責返回一個對象,可以是HttpResponse對象,也可以render對象,還可以是redirect對象。  

    所以,我們可以將上面的from引入語句修改得全一點,如下:   

from django.shortcuts import render, HttpResponse, redirect

    在平時的開發中,我們也會稱 render, HttpResponse, redirect  這三個為 “ 基礎必配三件套 ”  

    注意,HttpResponse是一個類,而render和redirect是Django的內置函數!

Django使用請求和響應對象來通過系統傳遞狀態。

當瀏覽器向服務端請求一個頁面時,Django創建一個HttpRequest對象,該對象包含關於請求的元數據。然后,Django加載相應的視圖,將這個HttpRequest對象作為第一個參數傳遞給視圖函數。

每個視圖負責返回一個HttpResponse對象給瀏覽器。

2. 視圖函數的前奏(FBV和CBV)

什么是FBV?   在視圖文件里面編輯的時候,基於函數的形式來編輯業務邏輯的視圖view,就叫做FBV (function base view)。

什么是CBV?   而在編輯業務邏輯的時候,基於類的形式來編輯業務邏輯的則是叫做CBV(class base view)。

下面用一個簡單的例子來說明:

使用FBV寫:

 

from django.shortcuts import render, HttpResponse, redirect def back_hello(request): return HttpResponse('大家好!')

 

使用CBV寫:

from django.views import View    # 基於類的形式來寫試圖上的業務邏輯的時候,定義的類需要 繼承 django 中的View類 !!!!!!!
class BackHello(View): def get(self, request): return HttpResponse("get請求的時候!get大家好!") def post(self, request): return HttpResponse("post請求的時候!post大家好!")

注意:使用CBV形式的時候,urls.py上的路徑與函數的對應關系,是與FBV不一樣的,需要修改,如下:

urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test/', views.BackHello.as_view()), ] # 可以看出,test/位置中的路徑寫法與FBV一樣,時候后面的引入格式變成了:
# views.類名.as_view()。而CBV情況下是寫為: views.函數名 # 注意:as_view(),這個是固定的!!!!

3. Django視圖函數

視圖函數,簡稱視圖,本質上就是一個Python函數,只是他在django的框架下能做一些特殊的相應,比如它可以接受Web請求做出一些邏輯運算,並且返回Web響應。

響應的內容可以是HTML網頁、重定向、404錯誤,XML文檔或圖像等任何東西。但是,無論視圖本身是個什么處理邏輯,必須都要有一個返回某種響應。

通常我們約定將視圖放置在項目或應用程序目錄中的名為views.py的文件中,而視圖函數也是放在視圖文件當中,這也是一種模塊化思維,把各種功能規划好,方便未來的管理。

4. Django內置快捷方法(函數)

Django在django.shortcuts模塊中,為我們提供了很多快捷方便的內置函數,其中有些使用的頻率很高!

4.1  render()

Django關於render的源碼如下:

 

 

結合一個給定的模板和一個給定的上下文字典,並返回一個渲染后的 HttpResponse 對象。

參數:
  必備(常用)參數: request: 用於生成響應的請求對象。 template_name:要使用的模板的完整名稱,可選的參數 context:添加到模板上下文的一個字典。默認是一個空字典。如果字典中的某個值是可調用的,視圖將在渲染模板之前調用它。  
  可以選參數: content_type:生成的文檔要使用的MIME類型。默認為 DEFAULT_CONTENT_TYPE 設置的值。默認為'text/html' status:響應的狀態碼。默認為200。


   useing: 用於加載模板的模板引擎的名稱。
一個簡單的例子:
from django.shortcuts import render

def my_view(request):
    # 視圖的代碼寫在這里
    return render(request, 'myapp/index.html', {'foo': 'bar'})

上面的代碼等於:

復制代碼
from django.http import HttpResponse
from django.template import loader

def my_view(request):
    # 視圖代碼寫在這里
    t = loader.get_template('myapp/index.html')
    c = {'foo': 'bar'}
    return HttpResponse(t.render(c, request))
復制代碼

4.2  redirect()

參數:參數范圍相對render來說比較廣

  • 一個模型:將調用模型的get_absolute_url() 函數
  • 一個視圖,可以帶有參數:將使用urlresolvers.reverse 來反向解析名稱
  • 一個絕對的或相對的URL,將原封不動的作為重定向的位置。

默認返回一個臨時的重定向;傳遞一個參數名為 permanent=True 就可以返回一個永久的重定向。

redirect使用的兩個場景:其中,第一個場景使用的比較多!!!!

1. 傳遞視圖名,使用reverse()方法反向解析url:

from django.shortcuts import redirect
def
my_view(request): ... return redirect('some-view-name', foo='bar')

  1.1 重定向到硬編碼的URL:

def my_view(request): ... return redirect('/some/url/')

  1.2 重定向到一個完整的URL:

def my_view(request): ... return redirect('https://example.com/')

2. 調用對象的get_absolute_url()方法來重定向URL:

def my_view(request): ... object = MyModel.objects.get(...) return redirect(object)

所有上述形式都接受permanent參數;如果設置為True,將返回永久重定向:

def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True)

5. 什么是臨時重定向?永久重定向?

臨時重定向的響應狀態碼:302

永久重定向的響應狀態碼:301

這兩個的狀態碼對於普通的用戶來說是沒有任何區別,因為他們主要針對的是搜索引擎機器人。

這就涉及到了,另外一個領域了,這就是SEO工作人員的必配只是!

A頁面臨時重定向到B頁面,那搜索引擎收錄的就是A頁面。

A頁面永久重定向到B頁面,那搜索引擎收錄的就是B頁面。

6. Django兩個重要對象

6.1  request對象

每當一個用戶請求發送過來,Django將HTTP數據包中的相關內容,打包成為一個HttpRequest對象,並傳遞給每個視圖函數作為第一位置參數,也就是request,供我們調用。

說明為什么別的教程會叫HttpRequst對象?:這里說是request對象是不太嚴謹的,因為我們指的request只是每一個視圖函數中,固定的第一位置的一個參數名稱。至於為什么我們要取名為request,只是一個大家約定熟成而已,再者就是名稱比HttpRequest短,大家更加好記 ~_~ 。所以,真正的應該是對象應該是,HttpRequest類生產的一個對象,所以在別的地方,也會成為HttpRequest對象。

6.1.1  請求相關的常用值

  其實也是屬於request的屬性,只是平時使用頻率很高,所以把它放大到前面一些,方便大家學習。

  • path_info     返回用戶訪問url,不包括域名
  • method        請求中使用的HTTP方法的字符串表示,全大寫表示。
  • GET              包含所有HTTP  GET參數的類字典對象
  • POST           包含所有HTTP POST參數的類字典對象
  • body            請求體,byte類型 request.POST的數據就是從body里面提取到的

6.1.2   request對象的屬性:

  下面的把request說成HttpRequest,這兩個是沒有區別的哦!!!!!上面也做了解釋了

屬性:   django將請求報文中的請求行、頭部信息、內容主體封裝成 HttpRequest 類中的屬性。 除了特殊說明的之外,其他均為只讀的。 0.HttpRequest.scheme 表示請求方案的字符串(通常為http或https) 1.HttpRequest.body   一個字符串,代表請求報文的主體。在處理非 HTTP 形式的報文時非常有用,例如:二進制圖片、XML,Json等。   但是,如果要處理表單數據的時候,推薦還是使用 HttpRequest.POST 。   另外,我們還可以用 python 的類文件方法去操作它,詳情參考 HttpRequest.read() 。 2.HttpRequest.path   一個字符串,表示請求的路徑組件(不含域名)。   例如:"/music/bands/the_beatles/"

3.HttpRequest.method   一個字符串,表示請求使用的HTTP 方法。必須使用大寫。   例如:"GET""POST"

4.HttpRequest.encoding   一個字符串,表示提交的數據的編碼方式(如果為 None 則表示使用 DEFAULT_CHARSET 的設置,默認為 'utf-8')。 這個屬性是可寫的,你可以修改它來修改訪問表單數據使用的編碼。 接下來對屬性的任何訪問(例如從 GET 或 POST 中讀取數據)將使用新的 encoding 值。 如果你知道表單數據的編碼不是 DEFAULT_CHARSET ,則使用它。 5.HttpRequest.GET   一個類似於字典的對象,包含 HTTP GET 的所有參數。詳情請參考 QueryDict 對象。點我知道 >>> 什么是QueryDict對象?
6.HttpRequest.POST   一個類似於字典的對象,如果請求中包含表單數據,則將這些數據封裝成 QueryDict 對象。   POST 請求可以帶有空的 POST 字典 —— 如果通過 HTTP POST 方法發送一個表單,但是表單中沒有任何的數據,QueryDict 對象依然會被創建。 因此,不應該使用 if request.POST 來檢查使用的是否是POST 方法;應該使用 if request.method == "POST"   另外:如果使用 POST 上傳文件的話,文件信息將包含在 FILES 屬性中。 7.HttpRequest.COOKIES   一個標准的Python 字典,包含所有的cookie。鍵和值都為字符串。 8.HttpRequest.FILES   一個類似於字典的對象,包含所有的上傳文件信息。 FILES 中的每個鍵為<input type="file" name="" /> 中的name,值則為對應的數據。   注意,FILES 只有在請求的方法為POST 且提交的<form> 帶有enctype="multipart/form-data" 的情況下才會 包含數據。否則,FILES 將為一個空的類似於字典的對象。 9.HttpRequest.META   一個標准的Python 字典,包含所有的HTTP 首部。具體的頭部信息取決於客戶端和服務器,下面是一些示例: CONTENT_LENGTH —— 請求的正文的長度(是一個字符串)。 CONTENT_TYPE —— 請求的正文的MIME 類型。 HTTP_ACCEPT —— 響應可接收的Content-Type。 HTTP_ACCEPT_ENCODING —— 響應可接收的編碼。 HTTP_ACCEPT_LANGUAGE —— 響應可接收的語言。 HTTP_HOST —— 客服端發送的HTTP Host 頭部。 HTTP_REFERER —— Referring 頁面。 HTTP_USER_AGENT —— 客戶端的user-agent 字符串。 QUERY_STRING —— 單個字符串形式的查詢字符串(未解析過的形式)。 REMOTE_ADDR —— 客戶端的IP 地址。 REMOTE_HOST —— 客戶端的主機名。 REMOTE_USER —— 服務器認證后的用戶。 REQUEST_METHOD —— 一個字符串,例如"GET""POST"。 SERVER_NAME —— 服務器的主機名。 SERVER_PORT —— 服務器的端口(是一個字符串)。   從上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,請求中的任何 HTTP 首部轉換為 META 的鍵時, 都會將所有字母大寫並將連接符替換為下划線最后加上 HTTP_ 前綴。 所以,一個叫做 X-Bender 的頭部將轉換成 META 中的 HTTP_X_BENDER 鍵。 10.HttpRequest.user   一個 AUTH_USER_MODEL 類型的對象,表示當前登錄的用戶。   如果用戶當前沒有登錄,user 將設置為 django.contrib.auth.models.AnonymousUser 的一個實例。你可以通過 is_authenticated() 區分它們。 例如: if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users.   user 只有當Django 啟用 AuthenticationMiddleware 中間件時才可用。 ------------------------------------------------------------------------------------- 匿名用戶 class models.AnonymousUser django.contrib.auth.models.AnonymousUser 類實現了django.contrib.auth.models.User 接口,但具有下面幾個不同點: id 永遠為None。 username 永遠為空字符串。 get_username() 永遠返回空字符串。 is_staff 和 is_superuser 永遠為False。 is_active 永遠為 False。 groups 和 user_permissions 永遠為空。 is_anonymous() 返回True 而不是False。 is_authenticated() 返回False 而不是True。 set_password()、check_password()、save() 和delete() 引發 NotImplementedError。 New in Django 1.8: 新增 AnonymousUser.get_username() 以更好地模擬 django.contrib.auth.models.User。 11.HttpRequest.session   一個既可讀又可寫的類似於字典的對象,表示當前的會話。只有當Django 啟用會話的支持時才可用。 完整的細節參見會話的文檔。 request屬性相關

示例:正在更新中………………

6.1.2   request對象的方法:

 1 1.HttpRequest.get_host()
 2 
 3   根據從HTTP_X_FORWARDED_HOST(如果打開 USE_X_FORWARDED_HOST,默認為False)和 HTTP_HOST 頭部信息返回請求的原始主機。
 4    如果這兩個頭部沒有提供相應的值,則使用SERVER_NAME 和SERVER_PORT,在PEP 3333 中有詳細描述。
 5 
 6   USE_X_FORWARDED_HOST:一個布爾值,用於指定是否優先使用 X-Forwarded-Host 首部,僅在代理設置了該首部的情況下,才可以被使用。
 7 
 8   例如:"127.0.0.1:8000"
 9 
10   注意:當主機位於多個代理后面時,get_host() 方法將會失敗。除非使用中間件重寫代理的首部。
11 
12  
13 
14 2.HttpRequest.get_full_path()
15 
16   返回 path,如果可以將加上查詢字符串。
17 
18   例如:"/music/bands/the_beatles/?print=true"
19 
20  
21 
22 3.HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
23 
24   返回簽名過的Cookie 對應的值,如果簽名不再合法則返回django.core.signing.BadSignature。
25 
26   如果提供 default 參數,將不會引發異常並返回 default 的值。
27 
28   可選參數salt 可以用來對安全密鑰強力攻擊提供額外的保護。max_age 參數用於檢查Cookie 對應的時間戳以確保Cookie 的時間不會超過max_age 秒。
29 
30         復制代碼
31         >>> request.get_signed_cookie('name')
32         'Tony'
33         >>> request.get_signed_cookie('name', salt='name-salt')
34         'Tony' # 假設在設置cookie的時候使用的是相同的salt
35         >>> request.get_signed_cookie('non-existing-cookie')
36         ...
37         KeyError: 'non-existing-cookie'    # 沒有相應的鍵時觸發異常
38         >>> request.get_signed_cookie('non-existing-cookie', False)
39         False
40         >>> request.get_signed_cookie('cookie-that-was-tampered-with')
41         ...
42         BadSignature: ...    
43         >>> request.get_signed_cookie('name', max_age=60)
44         ...
45         SignatureExpired: Signature age 1677.3839159 > 60 seconds
46         >>> request.get_signed_cookie('name', False, max_age=60)
47         False
48         復制代碼
49          
50 
51 
52 4.HttpRequest.is_secure()
53 
54   如果請求時是安全的,則返回True;即請求通是過 HTTPS 發起的。
55 
56  
57 
58 5.HttpRequest.is_ajax()
59 
60   如果請求是通過XMLHttpRequest 發起的,則返回True,方法是檢查 HTTP_X_REQUESTED_WITH 相應的首部是否是字符串'XMLHttpRequest'61 
62   大部分現代的 JavaScript 庫都會發送這個頭部。如果你編寫自己的 XMLHttpRequest 調用(在瀏覽器端),你必須手工設置這個值來讓 is_ajax() 可以工作。
63 
64   如果一個響應需要根據請求是否是通過AJAX 發起的,並且你正在使用某種形式的緩存例如Django 的 cache middleware, 
65    你應該使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 裝飾你的視圖以讓響應能夠正確地緩存。
66 
67 請求相關方法
5個request常用的方法

注意:鍵值對的值是多個的時候,比如checkbox類型的input標簽,select標簽,也就是一個標簽可能會有很多值的時候,

需要用下面的getlist方法來獲取多個值:

request.POST.getlist("hobby")

6.2 Response對象

HttpResponse類定義在django.http模塊中。

HttpRequest對象由Django自動創建,而HttpResponse對象則由程序員手動創建.

我們編寫的每個視圖都要實例化、填充和返回一個HttpResponse對象。也就是函數的return值。

 

6.2.1  使用方法

  1.  傳遞一個字符串

最簡單的方式是傳遞一個字符串作為頁面的內容到HttpResponse構造函數,並返回給用戶:

from django.http import HttpResponse response = HttpResponse("Here's the text of the Web page.") response = HttpResponse("Text only, please.", content_type="text/plain")

  2.  傳遞可迭代對象

HttpResponse會立即處理這個迭代器,並把它的內容存成字符串,最后廢棄這個迭代器。比如文件在讀取后,會立刻調用close()方法,關閉文件。

  3.  設置或刪除響應頭信息

response = HttpResponse() response['Content-Type'] = 'text/html; charset=UTF-8'
del response['Content-Type']

6.2.2 Response對象的屬性

前面三個重點記憶:
1. HttpResponse.content 響應的內容。bytes類型。 2. HttpResponse.charset 編碼的字符集。 如果沒指定,將會從content_type中解析出來。 3. HttpResponse.status_code 響應的狀態碼,比如200。
后面三個盡力而為:
4. HttpResponse.reason_phrase 響應的HTTP原因短語。 使用標准原因短語。 除非明確設置,否則reason_phrase由status_code的值決定。 5. HttpResponse.streaming 這個屬性的值總是False。由於這個屬性的存在,使得中間件能夠區別對待流式響應和常規響應。 6. HttpResponse.closed 如果響應已關閉,那么這個屬性的值為True。

6.3  JsonResponse類對象

JsonResponse是HttpResponse的子類,專門用來生成JSON編碼的響應。

大白話的說:就是JsonResponse類,可以把一些數據類型,比如:字典,列表,元組,集合等數據類型的結構,轉換成為字符串,以便用於轉遞到別的地方,提供別人使用!!!!

例如:有一個字典dict = {"aa":11, "bb":22},此時的dict只是一個字典(數據類型),當把字典dict經過JsonResponse類的內部變換之后,會把dict變成字符串 ” {"aa":11, "bb":22} “,注意字典兩邊的大括號都會一起變成字符串!!!!

from django.http import JsonResponse

response = JsonResponse({'foo': 'bar'})
print(response.content)

b'{"foo": "bar"}'

JsonResponse默認只能傳遞字典類型,如果要傳遞非字典類型需要設置一下safe關鍵字參數。

response = JsonResponse([1, 2, 3], safe=False)

什么是QueryDict對象?

類的原型:class QueryDict[source]

在HttpRequest對象中,GET和POST屬性都是一個django.http.QueryDict的實例。也就是說你可以按本文下面提供的方法操作request.POST和request.GET。

request.POST或request.GET的QueryDict都是不可變,只讀的。如果要修改它,需要使用QueryDict.copy()方法,獲取它的一個拷貝,然后在這個拷貝上進行修改操作。

一、方法
QueryDict 實現了Python字典數據類型的所有標准方法,因為它是字典的子類。

不同之處在於下面:

1. QueryDict.init(query_string=None, mutable=False, encoding=None)[source]
QueryDict實例化方法。注意:QueryDict的鍵值是可以重復的!

>>> QueryDict('a=1&a=2&c=3')
<QueryDict: {'a': ['1', '2'], 'c': ['3']}>
如果需要實例化可以修改的對象,添加參數mutable=True2. classmethod QueryDict.fromkeys(iterable, value='', mutable=False, encoding=None)[source]
Django1.11中的新功能。

循環可迭代對象中的每個元素作為鍵值,並賦予同樣的值(來至value參數)。

>>> QueryDict.fromkeys(['a', 'a', 'b'], value='val')
<QueryDict: {'a': ['val', 'val'], 'b': ['val']}>
3. QueryDict.update(other_dict)
用新的QueryDict或字典更新當前QueryDict。類似dict.update(),但是追加內容,而不是更新並替換它們。 像這樣:

>>> q = QueryDict('a=1', mutable=True)
>>> q.update({'a': '2'})
>>> q.getlist('a')
['1', '2']
>>> q['a'] # returns the last
'2'
4. QueryDict.items()
類似dict.items(),如果有重復項目,返回最近的一個,而不是都返回:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.items()
[('a', '3')]
5. QueryDict.values()
類似dict.values(),但是只返回最近的值。 像這樣:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.values()
['3']
6. QueryDict.copy()[source]
使用copy.deepcopy()返回QueryDict對象的副本。 此副本是可變的!

7. QueryDict.getlist(key, default=None)
返回鍵對應的值列表。 如果該鍵不存在並且未提供默認值,則返回一個空列表。

8. QueryDict.setlist(key, list_)[source]
為list_設置給定的鍵。

9. QueryDict.appendlist(key, item)[source]
將鍵追加到內部與鍵相關聯的列表中。

10. QueryDict.setdefault(key, default=None)[source]
類似dict.setdefault(),為某個鍵設置默認值。

11. QueryDict.setlistdefault(key, default_list=None)[source]
類似setdefault(),除了它需要的是一個值的列表而不是單個值。

12. QueryDict.lists()
類似items(),只是它將其中的每個鍵的值作為列表放在一起。 像這樣:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.lists()
[('a', ['1', '2', '3'])]
13. QueryDict.pop(key)[source]
返回給定鍵的值的列表,並從QueryDict中移除該鍵。 如果鍵不存在,將引發KeyError。 像這樣:

>>> q = QueryDict('a=1&a=2&a=3', mutable=True)
>>> q.pop('a')
['1', '2', '3']
14. QueryDict.popitem()[source]
刪除QueryDict任意一個鍵,並返回二值元組,包含鍵和鍵的所有值的列表。在一個空的字典上調用時將引發KeyError。 像這樣:

>>> q = QueryDict('a=1&a=2&a=3', mutable=True)
>>> q.popitem()
('a', ['1', '2', '3'])
15. QueryDict.dict()
將QueryDict轉換為Python的字典數據類型,並返回該字典。

如果出現重復的鍵,則將所有的值打包成一個列表,最為新字典中鍵的值。

>>> q = QueryDict('a=1&a=3&a=5')
>>> q.dict()
{'a': '5'}
16. QueryDict.urlencode(safe=None)[source]
已url的編碼格式返回數據字符串。 像這樣:

>>> q = QueryDict('a=2&b=3&b=5')
>>> q.urlencode()
'a=2&b=3&b=5'
使用safe參數傳遞不需要編碼的字符。 像這樣:

>>> q = QueryDict(mutable=True)
>>> q['next'] = '/a&b/'
>>> q.urlencode(safe='/')
'next=/a%26b/'
QueryDict對象內容

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM