day19_雷神_django次日

django_day02

Django的路由系統

URL配置(URLconf)就像Django所支撐網站的目錄。它的本質是URL與要爲該URL調用的視圖函數之間的映射表。css

一、URLconf配置

基本格式:html

from django.conf.urls import url

urlpatterns = [
     url(正則表達式, views視圖,參數,別名),
]

注意:前端

Django 2.0版本中的路由系統是下面的寫法(官方文檔):python

from django.urls import path,re_path

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]

二、正則表達式詳解

基本配置git

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

注意事項ajax

  • urlpatterns中的元素按照書寫順序從上往下逐一匹配正則表達式,一旦匹配成功則再也不繼續。
  • 若要從URL中捕獲一個值,只須要在它周圍放置一對圓括號(分組匹配)。
  • 不須要添加一個前導的反斜槓,由於每一個URL 都有。例如,應該是^articles 而不是 ^/articles。
  • 每一個正則表達式前面的'r' 是可選的可是建議加上。

補充說明正則表達式

# 是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑的配置項
APPEND_SLASH=True  默認就是True

若是在settings.py中設置了 APPEND_SLASH=False,此時咱們再請求 http://www.example.com/blog 時就會提示找不到頁面。

三、 分組命名規則

上面的示例使用簡單的正則表達式分組匹配(經過圓括號)來捕獲URL中的值並以位置參數形式傳遞給視圖。數據庫

在更高級的用法中,可使用分組命名匹配的正則表達式組來捕獲URL中的值並以關鍵字參數形式傳遞給視圖。django

在Python的正則表達式中,分組命名正則表達式組的語法是(?P pattern),其中name是組的名稱,pattern是要匹配的模式。 json

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

這個實現與前面的示例徹底相同,只有一個細微的差異:捕獲的值做爲關鍵字參數而不是位置參數傳遞給視圖函數。

URLconf匹配的位置

URLconf 在請求的URL 上查找,將它當作一個普通的Python 字符串。不包括GET和POST參數以及域名。

例如,http://www.example.com/myapp/ 請求中,URLconf 將查找 /myapp/ 。

在http://www.example.com/myapp/?page=3 請求中,URLconf 仍將查找 /myapp/ 。

URLconf 不檢查請求的方法。換句話講,全部的請求方法 —— 同一個URL的POST、GET、HEAD等等 —— 都將路由到相同的函數。

捕獲的參數永遠都是字符串

每一個在URLconf中捕獲的參數都做爲一個普通的Python字符串傳遞給視圖,不管正則表達式使用的是什麼匹配方式。例如,下面這行URLconf 中:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

傳遞到視圖函數views.year_archive() 中的year參數永遠是一個字符串類型。

視圖函數中指定默認值

# urls.py中
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# views.py中,能夠爲num指定默認值
def page(request, num="1"):
    pass

在上面的例子中,兩個URL模式指向相同的view - views.page - 可是第一個模式並無從URL中捕獲任何東西。

若是第一個模式匹配上了,page()函數將使用其默認參數num=「1」,若是第二個模式匹配,page()將使用正則表達式捕獲到的num值。

include其餘的URLconfs

from django.conf.urls import include, url

urlpatterns = [
   url(r'^admin/', admin.site.urls),
   url(r'^blog/', include('blog.urls')),  # 能夠包含其餘app的URLconfs文件
]

四、傳遞額外的參數給視圖函數(瞭解)

URLconfs 具備一個鉤子,讓你傳遞一個Python 字典做爲額外的參數傳遞給視圖函數。

django.conf.urls.url() 能夠接收一個可選的第三個參數,它是一個字典,表示想要傳遞給視圖函數的額外關鍵字參數。

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

在這個例子中,對於/blog/2005/請求,Django 將調用views.year_archive(request, year='2005', foo='bar')。
當傳遞額外參數的字典中的參數和URL中捕獲值的命名關鍵字參數同名時,函數調用時將使用的是字典中的參數,而不是URL中捕獲的參數。

五、 命名URL和URL反向解析

我們簡單來講就是能夠給咱們的URL匹配規則起個名字,一個URL匹配模式起一個名字。

這樣咱們之後就不須要寫死URL代碼了,只須要經過名字來調用當前的URL。

舉個簡單的例子:

url(r'^home', views.home, name='home'),  # 給個人url匹配模式起名爲 home
url(r'^index/(\d*)', views.index, name='index'),  # 給個人url匹配模式起名爲index

在模板裏面能夠這樣引用:

{% url 'home' %}

在views函數中能夠這樣引用:

from django.urls import reverse

reverse("index", args=("2018", ))

例子:

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>

在Python 代碼中,這樣使用:

from django.urls import reverse
from django.shortcuts import redirect

def redirect_to_year(request):
    # ...
    year = 2006
    # ...
    return redirect(reverse('news-year-archive', args=(year,)))

六、命名空間模式

即便不一樣的APP使用相同的URL名稱,URL的命名空間模式也可讓你惟一反轉命名的URL。

命名分組
        url(r'^pub/edit/(?P<pk>\d+)/$', views.publisher_edit,name='publisher_edit'),
        
        模板中使用:
            {% url 'publisher'%}   ——》/app01/publisher_list/
            
            命名分組
            {% url 'publisher_edit' publisher.id %}
            {% url 'publisher_edit' pk=publisher.id %}
            
        視圖中使用:
            from django.urls import reverse
            reverse('publisher')
            
            命名分組
            reverse('publisher_edit',args=(2,))
            reverse('publisher_edit',kwargs={'pk':5})
            
            
        指定namespace='app01'  
            反向解析的時候  給name前面加上namespace   ——》     namespace:name

Django的View(視圖)

一個視圖函數(類),簡稱視圖,是一個簡單的Python 函數(類),它接受Web請求而且返回Web響應。

一、一個簡單的視圖

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

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

每一個視圖負責返回一個HttpResponse對象。

二、 CBV和FBV

咱們以前寫過的都是基於函數的view,就叫FBV。還能夠把view寫成基於類的。 function based view.

FBV版本

# FBV版添加班級
def add_class(request):
    if request.method == "POST":
        class_name = request.POST.get("class_name")
        models.Classes.objects.create(name=class_name)
        return redirect("/class_list/")
    return render(request, "add_class.html")

CBV版本

# CBV版添加班級

from django.views import View


class AddClass(View):

    def get(self, request):
        return render(request, "add_class.html")

    def post(self, request):
        class_name = request.POST.get("class_name")
        models.Classes.objects.create(name=class_name)
        return redirect("/class_list/")

使用CBV時,urls.py中也作對應的修改:

url(r'^add_class/$', views.AddClass.as_view()),

三、裝飾器的使用

FBV: 正常使用 給函數上加裝飾器

def wrapper(func):
def inner(*args, **kwargs):
    start_time = time.time()
    ret = func(*args, **kwargs)
    end_time = time.time()
    print("used:", end_time-start_time)
    return ret
return inner


# FBV版添加班級
@wrapper
def add_class(request):
    if request.method == "POST":
        class_name = request.POST.get("class_name")
        models.Classes.objects.create(name=class_name)
        return redirect("/class_list/")
    return render(request, "add_class.html")

使用裝飾器裝飾CBV

# CBV版添加班級
from django.views import View
from django.utils.decorators import method_decorator

class AddClass(View):

    @method_decorator(wrapper)
    def get(self, request):
        return render(request, "add_class.html")

    def post(self, request):
        class_name = request.POST.get("class_name")
        models.Classes.objects.create(name=class_name)
        return redirect("/class_list/")

裝飾器的使用:

FBV: 正常使用 給函數上加裝飾器
    CBV:
        from django.utils.decorators import method_decorator
        
        1. 加在方法上
            @method_decorator(timer)
            def get(self, request):
            
        2. 加在dispatch方法上
            @method_decorator(timer)
            def dispatch(self, request, *args, **kwargs):
            
        3. 加在類上
            @method_decorator(timer,name='post')
            @method_decorator(timer,name='get')
            class AddPublisher(View):

CBV的流程

1. AddPublisher.as_view()  ——》 view函數
2. 請求到來的時候 執行view函數
    1. AddPublisher實例化 對象  ——》 self 
    2. self.request = request
    3. 執行self.dispatch(request, *args, **kwargs)
        1. 經過反射 獲取到 get  post 方法  ——>handler
    
        2. handler()  ——》  得到HttpResponse對象
  1. 直接用裝飾器
(<app01.views.AddPublisher object at 0x0000023DE99E57B8>, <WSGIRequest: GET '/app01/pub/add/'>)
                <function AddPublisher.get at 0x0000023DE992ED08>
  1. 使用method_decorator
(<WSGIRequest: GET '/app01/pub/add/'>,)
                <function method_decorator.<locals>._dec.<locals>._wrapper.<locals>.bound_func at 0x0000023372154EA0>

四、Request對象

請求相關的經常使用值

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

屬性

屬性:
  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 對象。

 

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 啓用會話的支持時纔可用。
    完整的細節參見會話的文檔。

上傳文件示例

def upload(request):
    """
    保存上傳文件前,數據須要存放在某個位置。默認當上傳文件小於2.5M時,django會將上傳文件的所有內容讀進內存。從內存讀取一次,寫磁盤一次。
    但當上傳文件很大時,django會把上傳文件寫到臨時文件中,而後存放到系統臨時文件夾中。
    :param request: 
    :return: 
    """
    if request.method == "POST":
        # 從請求的FILES中獲取上傳文件的文件名,file爲頁面上type=files類型input的name屬性值
        filename = request.FILES["file"].name
        # 在項目目錄下新建一個文件
        with open(filename, "wb") as f:
            # 從上傳的文件對象中一點一點讀
            for chunk in request.FILES["file"].chunks():
                # 寫入本地文件
                f.write(chunk)
        return HttpResponse("上傳OK")

頁面:

<body>
<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="file" name="file">
    <button type="submit">上傳</button>
</form>
</body>

請求相關方法

1.HttpRequest.get_host()

  根據從HTTP_X_FORWARDED_HOST(若是打開 USE_X_FORWARDED_HOST,默認爲False)和 HTTP_HOST 頭部信息返回請求的原始主機。
   若是這兩個頭部沒有提供相應的值,則使用SERVER_NAME 和SERVER_PORT,在PEP 3333 中有詳細描述。

  USE_X_FORWARDED_HOST:一個布爾值,用於指定是否優先使用 X-Forwarded-Host 首部,僅在代理設置了該首部的狀況下,才能夠被使用。

  例如:"127.0.0.1:8000"

  注意:當主機位於多個代理後面時,get_host() 方法將會失敗。除非使用中間件重寫代理的首部。

 

2.HttpRequest.get_full_path()

  返回 path,若是能夠將加上查詢字符串。

  例如:"/music/bands/the_beatles/?print=true"

 

3.HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

  返回簽名過的Cookie 對應的值,若是簽名再也不合法則返回django.core.signing.BadSignature。

  若是提供 default 參數,將不會引起異常並返回 default 的值。

  可選參數salt 能夠用來對安全密鑰強力攻擊提供額外的保護。max_age 參數用於檢查Cookie 對應的時間戳以確保Cookie 的時間不會超過max_age 秒。

        複製代碼
        >>> request.get_signed_cookie('name')
        'Tony'
        >>> request.get_signed_cookie('name', salt='name-salt')
        'Tony' # 假設在設置cookie的時候使用的是相同的salt
        >>> request.get_signed_cookie('non-existing-cookie')
        ...
        KeyError: 'non-existing-cookie'    # 沒有相應的鍵時觸發異常
        >>> request.get_signed_cookie('non-existing-cookie', False)
        False
        >>> request.get_signed_cookie('cookie-that-was-tampered-with')
        ...
        BadSignature: ...    
        >>> request.get_signed_cookie('name', max_age=60)
        ...
        SignatureExpired: Signature age 1677.3839159 > 60 seconds
        >>> request.get_signed_cookie('name', False, max_age=60)
        False
        複製代碼
         


4.HttpRequest.is_secure()

  若是請求時是安全的,則返回True;即請求通是過 HTTPS 發起的。

 

5.HttpRequest.is_ajax()

  若是請求是經過XMLHttpRequest 發起的,則返回True,方法是檢查 HTTP_X_REQUESTED_WITH 相應的首部是不是字符串'XMLHttpRequest'。

  大部分現代的 JavaScript 庫都會發送這個頭部。若是你編寫本身的 XMLHttpRequest 調用(在瀏覽器端),你必須手工設置這個值來讓 is_ajax() 能夠工做。

  若是一個響應須要根據請求是不是經過AJAX 發起的,而且你正在使用某種形式的緩存例如Django 的 cache middleware, 
   你應該使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 裝飾你的視圖以讓響應可以正確地緩存。

注意:鍵值對的值是多個的時候,好比checkbox類型的input標籤,select標籤,須要用:

request.POST.getlist("hobby")

五、Response對象

HttpResponse('字符串')
render(request,'html文件名',{})    完整的頁面
redirect(地址)  '/zz/'   'https://v3.bootcss.com/css/#forms'    Location :'/zz/'

JSON

方法一:
後端:
    在試圖函數中,return HttpResponse(json.dunps(data)),將字典轉化爲字符串。

前端:

    在瀏覽器得console裏,JSON.parse('{"name":"ALEX"}'),就把字符串轉換爲對象了

方法二:

from django.http import JsonResponse

return sonResponse({'foo': 'bar'}),瀏覽器不用parse了。

方法三:(設置響應頭得方式)
def data_json(request):
    data = {'name': 'alex', 'age': 73}
    data_list = [1, 22, 34, ]
    ret = HttpResponse(json.dumps(data))
    ret['Content-Type'] = 'application/json'
    # return ret  # Content-Type: text/html; charset=utf-8
    return JsonResponse(data_list, safe=False)  # Content-Type: application/json

注意:

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

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

Django模板系統

一、經常使用語法

Django模板中只須要記兩種特殊符號:

{{  }}和 {% %}

{{ }}表示變量,在模板渲染的時候替換成值,{% %}表示邏輯相關的操做。

變量

view中代碼:

def template_test(request):
    l = [11, 22, 33]
    d = {"name": "alex"}

    class Person(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age

        def dream(self):
            return "{} is dream...".format(self.name)

    Alex = Person(name="Alex", age=34)
    Egon = Person(name="Egon", age=9000)
    Eva_J = Person(name="Eva_J", age=18)

    person_list = [Alex, Egon, Eva_J]
    return render(request, "template_test.html", {"l": l, "d": d, "person_list": person_list})

模板中支持的寫法:

{# 取l中的第一個參數 #}
{{ l.0 }}
{# 取字典中key的值 #}
{{ d.name }}
{# 取對象的name屬性 #}
{{ person_list.0.name }}
{# .操做只能調用不帶參數的方法 #}
{{ person_list.0.dream }}

注意:

注:當模板系統遇到一個(.)時,會按照以下的順序去查詢:

在字典中查詢
屬性或者方法
數字索引

Filters

翻譯爲過濾器,用來修改變量的顯示結果。

語法: {{ value|filter_name:參數 }}

'|'左右沒有空格沒有空格沒有空格

default  

{{ value|default:"nothing"}}
若是value值沒傳的話就顯示nothing

filesizeformat

將值格式化爲一個 「人類可讀的」 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:

{{ value|filesizeformat }}

add

{{ value|add:"2" }}
value是數字4,則輸出結果爲6。

{{ first|add:second }}
若是first是 [1,.2,3] ,second是 [4,5,6] ,那輸出結果是 [1,2,3,4,5,6] 。

lower

小寫

{{ value|lower }}

length

{{ value|length }}

返回value的長度,如 value=['a', 'b', 'c', 'd']的話,就顯示4.

date

日期格式化

{{ value|date:"Y-m-d H:i:s"}}

全局的配置:
    在settings裏面寫:
    DATATIME_FORMAT = 'Y-m-d H:i:s'
    USE_LION = False

safe

爲了在Django中關閉HTML的自動轉義有兩種方式,若是是一個單獨的變量咱們能夠經過過濾器「|safe」的方式告訴Django這段代碼是安全的沒必要轉義。

好比:

value = "<a href='#'>點我</a>"

{{ value|safe}}

二、 tag 標籤

for循環可用的一些參數:

Variable    Description
forloop.counter 當前循環的索引值(從1開始)
forloop.counter0    當前循環的索引值(從0開始)
forloop.revcounter  當前循環的倒序索引值(從1開始)
forloop.revcounter0 當前循環的倒序索引值(從0開始)
forloop.first   當前循環是否是第一次循環(布爾值)
forloop.last    當前循環是否是最後一次循環(布爾值)
forloop.parentloop  本層循環的外層循環  須要引用外出循環的一些參數時候

for ... empty

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% empty %}
    <li>空空如也</li>
{% endfor %}
</ul>

示例:
    {% empty %}
    <tr><td colspan='4' style='text-aline:center'>沒有數據</td></tr>

csrf_token

這個標籤用於跨站請求僞造保護。

在頁面的form表單裏面寫上{% csrf_token %}

if,elif和else

{% if user_list %}
  用戶人數:{{ user_list|length }}
{% elif black_list %}
  黑名單數:{{ black_list|length }}
{% else %}
  沒有用戶
{% endif %}

if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷。

注意事項:

  1. Django的模板語言不支持連續判斷,即不支持如下寫法:

    {% if a > b > c %}
    ...
    {% endif %}

三、 母版

繼承母版

在子頁面中在頁面最上方使用下面的語法來繼承母板。

{% extends 'layouts.html' %}

塊(block)

經過在母板中使用{% block  xxx %}來定義"塊"。

在子頁面中經過定義母板中的block名來對應替換母板中相應的內容。

{% block page-main %}
  <p>世情薄</p>
  <p>人情惡</p>
  <p>雨送黃昏花易落</p>
{% endblock %}

組件

能夠將經常使用的頁面內容如導航條,頁尾信息等組件保存在單獨的文件中,而後在須要使用的地方按以下語法導入便可。

{% include 'navbar.html' %}

靜態文件相關

- {% load static %}
    
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7/css/bootstrap.css' %}"
    <link rel="stylesheet" href="{% static 'css/dsb.css' %}">}

    <link rel="stylesheet" href="{% get_static_prefix %}bootstrap-3.3.7/css/bootstrap.css">
    <link rel="stylesheet" href="{% get_static_prefix %}css/dsb.css">

Django的Object Relational Mapping(ORM)

經常使用字段

AutoField

自增的整形字段,必填參數primary_key=True,則成爲數據庫的主鍵。無該字段時,django自動建立。

一個model不能有兩個AutoField字段。

IntegerField

一個整數類型。數值的範圍是 -2147483648 ~ 2147483647。

CharField

字符類型,必須提供max_length參數。max_length表示字符的長度。

DateField

日期類型,日期格式爲YYYY-MM-DD,至關於Python中的datetime.date的實例。

參數:

auto_now:每次修改時修改成當前日期時間。
auto_now_add:新建立對象時自動添加當前日期時間。
auto_now和auto_now_add和default參數是互斥的,不能同時設置。

DatetimeField

日期時間字段,格式爲YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],至關於Python中的datetime.datetime的實例。

字段類型

AutoField(Field)
        - int自增列,必須填入參數 primary_key=True

    BigAutoField(AutoField)
        - bigint自增列,必須填入參數 primary_key=True

        注:當model中若是沒有自增列,則自動會建立一個列名爲id的列
        from django.db import models

        class UserInfo(models.Model):
            # 自動建立一個列名爲id的且爲自增的整數列
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # 自定義自增列
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)

    SmallIntegerField(IntegerField):
        - 小整數 -32768 ~ 32767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整數 0 ~ 32767

    IntegerField(Field)
        - 整數列(有符號的) -2147483648 ~ 2147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整數 0 ~ 2147483647

    BigIntegerField(IntegerField):
        - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807

    BooleanField(Field)
        - 布爾值類型

    NullBooleanField(Field):
        - 能夠爲空的布爾值

    CharField(Field)
        - 字符類型
        - 必須提供max_length參數, max_length表示字符長度

    TextField(Field)
        - 文本類型

    EmailField(CharField):
        - 字符串類型,Django Admin以及ModelForm中提供驗證機制

    IPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制

    GenericIPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6
        - 參數:
            protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
            unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓此功能,須要protocol="both"

    URLField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 URL

    SlugField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號)

    CommaSeparatedIntegerField(CharField)
        - 字符串類型,格式必須爲逗號分割的數字

    UUIDField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證

    FilePathField(Field)
        - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能
        - 參數:
                path,                      文件夾路徑
                match=None,                正則匹配
                recursive=False,           遞歸下面的文件夾
                allow_files=True,          容許文件
                allow_folders=False,       容許文件夾

    FileField(Field)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage

    ImageField(FileField)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage
            width_field=None,   上傳圖片的高度保存的數據庫字段名(字符串)
            height_field=None   上傳圖片的寬度保存的數據庫字段名(字符串)

    DateTimeField(DateField)
        - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 時間格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型

    FloatField(Field)
        - 浮點型

    DecimalField(Field)
        - 10進制小數
        - 參數:
            max_digits,小數總長度
            decimal_places,小數位長度

    BinaryField(Field)
        - 二進制類型

字段參數

null                數據庫中字段是否能夠爲空
db_column           數據庫中字段的列名
default             數據庫中字段的默認值
primary_key         數據庫中字段是否爲主鍵
db_index            數據庫中字段是否能夠創建索引
unique              數據庫中字段是否能夠創建惟一索引

Model Meta參數

class UserInfo(models.Model):
    nid = models.AutoField(primary_key=True)
    username = models.CharField(max_length=32)
 
    class Meta:
        # 數據庫中生成的表名稱 默認 app名稱 + 下劃線 + 類名
        db_table = "table_name"
 
        # 聯合索引 
        index_together = [
            ("pub_date", "deadline"),   # 應爲兩個存在的字段
        ]
 
        # 聯合惟一索引
        unique_together = (("driver", "restaurant"),)   # 應爲兩個存在的字段

ORM操做必會13條

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
import django
django.setup()

from app01 import models
# 獲取對象
ret = models.User.objects.get(id=1)
# 獲取所全部  ——》 對象列表
ret = models.User.objects.all()

# 獲取全部知足條件的對象   ——》對象列表
ret = models.User.objects.filter()

# 獲取全部不知足條件的對象   ——》對象列表
ret = models.User.objects.exclude(id=1)

# values  ——》對象列表   {}
# 不寫參數  拿全部字段name 和 value
# 寫參數  拿指定字段name 和 value
ret = models.User.objects.all().values('name','id')

# values_list  ——》對象列表   ()
# 不寫參數  拿全部字段value
# 寫參數  拿指定字段value
ret = models.User.objects.all().values_list('name','id')

ret = models.User.objects.all().order_by('age','-id')

ret = models.User.objects.all().order_by('id').reverse()

# distinct() 去重

ret = models.User.objects.all().count()

ret = models.User.objects.filter(id=100).exists()
print(ret)


"""
返回對象列表的方法
1. all()
2. filter()
3. exclude()
4. order_by()
5. reverse()
6. values() {}
7. values_list()  ()
8. distinct()

返回對象的
1. get()
2. first()
3. last()

返回布爾值
1. exists()

返回數字的
1. count()

"""

單表的雙下劃線查詢

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
import django
django.setup()

from app01 import models

ret = models.User.objects.filter(id__gt=1)  # greater than
ret = models.User.objects.filter(id__gte=1)  # greater than equal
ret = models.User.objects.filter(id__lt=5)  # less than
ret = models.User.objects.filter(id__lte=3)  # less than equal


ret = models.User.objects.filter(id__in=[1,3,5])
ret = models.User.objects.filter(id__range=[1,3])


ret = models.User.objects.filter(name__contains='e')
# ret = models.User.objects.filter(name__icontains='e')
ret = models.User.objects.filter(name__startswith='h')

ret = models.User.objects.filter(birth__year='2018')
ret = models.User.objects.filter(birth__month='10')
ret = models.User.objects.filter(birth__day='13')

print(ret)

外鍵的使用及查詢

正向查找

對象查找(跨表)

語法:

對象.關聯字段.字段 

示例:

book_obj = models.Book.objects.first()  # 第一本書對象
print(book_obj.publisher)  # 獲得這本書關聯的出版社對象
print(book_obj.publisher.name)  # 獲得出版社對象的名稱

字段查找(跨表)
語法:

關聯字段__字段

示例:

print(models.Book.objects.values_list("publisher__name"))
回到頂部

反向操做

對象查找

語法:

obj.表名_set

示例:

publisher_obj = models.Publisher.objects.first()  # 找到第一個出版社對象
books = publisher_obj.book_set.all()  # 找到第一個出版社出版的全部書
titles = books.values_list("title")  # 找到第一個出版社出版的全部書的書名

字段查找

語法:

表名__字段

示例:

titles = models.Publisher.objects.values_list("book__title")

示例:

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
import django
django.setup()

from app01 import models
obj=models.Book.objects.get(id=1)

print(obj.publisher)

ret = models.Book.objects.filter(publisher__name='沙河出版社')
# print(ret)


pub_obj = models.Publisher.objects.get(id=14)

print(pub_obj.book_set.all())

print(models.Publisher.objects.filter(book__title='九陽真經'))
相關文章
相關標籤/搜索