day16-python項目Django框架之基礎

 

第1章 Django之MTV模型

1.1 課堂總結記錄

Django

 

   1 流程:

       (1) 設計url: url(r'^timer/', timer), # timer(request)

       (2) 構建視圖函數:

           在views.py:

            def timer(request):

                import time

                ctime=time.time()

                return render(request,"timer.html",{"ctime":ctime})

               

        (3) templates:timer.html

                <p>當前時間:{{ ctime }}</p>

               

               

   

 

    2 URL控制器(路由層):

       

        簡單配置

        分組

        有名分組

        分發

        反向解析

       

   

    3 MTV--View(視圖層):

      

       請求對象

            request:

               request.GET

               request.POST

               request.method

               request.path

      

     

       響應對象:

            Httpresponse()

            render()

            redirect()

   

   

    4 MTV--Template(模板層)

   

          渲染變量 {{ }}

               深度查詢句點符

               過濾器{{ var|filter:參數}}

               add

               date

               safe

               filesizeformat     

              

          渲染標籤 {% %}

               for

               if

               url 反向解析

               csrftoken

          自定義過濾器和標籤

 

    4 MTV--Model(模型層)

   

        ORM---對象關係映射

       

            class Book(model.Model):

                title=models.CharFiled(max_length=32)

 

               

            create table book (

                 title varchar(32)         

            )

           

           

            類名        ------表名

            類屬性      ------表字段

            類實例對象  ------表記錄

           

       

           

   

        單表記錄操做:

            Book

                id    title

                1     python

                2     java

            添加記錄:

               # 方式1:

               # obj新添加記錄對象

               obj=Book.objects.create(title="python")

               # 方式2:

               obj=Book(title="java")

               obj.save()

 

            查詢記錄API(QuerySet):

           

                <1> all():                 查詢全部結果

 

                <2> filter(**kwargs):      它包含了與所給篩選條件相匹配的對象

                 

                <3> get(**kwargs):         返回與所給篩選條件相匹配的對象,返回結果有且只有一個,

                                           若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。

                <5> exclude(**kwargs):     它包含了與所給篩選條件不匹配的對象

                 

                <4> values(*field):        返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列

                                           model的實例化對象,而是一個可迭代的字典序列

                 

                <9> values_list(*field):      它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列

                 

                <6> order_by(*field):      對查詢結果排序

                 

                <7> reverse():             對查詢結果反向排序

                 

                <8> distinct():            從返回結果中剔除重複紀錄

                 

                <10> count():              返回數據庫中匹配查詢(QuerySet)的對象數量。

                 

                <11> first():              返回第一條記錄

                 

                <12> last():               返回最後一條記錄

                 

                <13> exists():            若是QuerySet包含數據,就返回True,不然返回False

               

               

                模糊查詢: __

               

               

               

            刪除記錄

                Book.objects.filter(price=123,title="python").delete()

 

            更新記錄:

                Book.objects.filter(price=123,title="python").update(title="python123")

   

    mysql表關係

   

    一對多關係:關聯字段

    多對多關係:建立關係表

   

    Book

       title=...

       publish=Foreignkey(to="Publish",to_field="")

       authors=

    Publish

       name=....

      

    Author

       name=....

   

    Book2Author

   

   

 
課堂筆記

1.2 MTV模型的含義

Django的MTV分別表明:css

  Model(模型):和數據庫相關的,負責業務對象與數據庫的對象(ORM)html

  Template(模板):放全部的html文件,負責如何把頁面展現給用戶前端

           模板語法:目的是將白變量(數據庫的內容)如何巧妙的嵌入到html頁面中java

  View(視圖):負責業務邏輯,並在適當的時候調用Model和Templatepython

  此外,Django還有一個URL分發器。它的做用是將一個個URL的頁面請求分別發給不一樣的Views處理,Views再調用相應的Model和Template。mysql

 

1.3 Django基本命令

1.3.1 下載Django:

pip3 install django

1.4 建立一個django project

建立一個Django項目分兩種方式建立:jquery

1.4.1 第一種方法使用pycharm軟件建立

文件——新建項目——切到Djangonginx

 

建立成功後會自動生成這樣一個工程。目錄結構以下:git

 

1.5 第二種命令行建立

1.5.1 建立一個Django對象

django-admin.py  startproject   項目名稱

django-admin startproject mysite

建立成功後會生成這樣一個工程。目錄結構以下:web

 

  • manage.py------啓動文件 (Django項目裏面的工具,經過它能夠調用Django shell的數目和數據庫等)
  • settings.py------包含了項目的一些設置,包括數據庫信息、調試標誌以及其餘一些工做的變量。
  • urls.py-----------路徑與視圖函數的映射關係

1.5.2 在mysite目錄下建立應用

python3 manage.py startapp blog(應用名稱)

建立成功後會生成這樣一個工程。目錄結構以下:

 

1.5.3 啓動django項目

python3 manage.py runserver 8080

這樣咱們的django就啓動起來了!當咱們訪問:http://127.0.0.1:8080/時就能夠看到:

 

1.6 建立表命令

1.6.1 同步更改數據庫表或字段

'''

    python3 manage.py syncdb

    

    注意:Django 1.7.1 及以上的版本須要用如下命令

    python3 manage.py makemigrations

    python3 manage.py migrate   

'''

這種方法能夠建立表,當你在models.py中新增了類時,運行它就能夠自動在數據庫中建立表了,不用手動建立。

 

1.6.2 清空數據庫

python3 manage.py flush

此命令會詢問是 yes 仍是 no, 選擇 yes 會把數據所有清空掉,只留下空表。

 

1.6.3 建立超級管理員

'''

    python3 manage.py createsuperuser

    

    # 按照提示輸入用戶名和對應的密碼就行了郵箱能夠留空,用戶名和密碼必填

    

    # 修改 用戶密碼能夠用:

    python3 manage.py changepassword username

   

'''

1.6.4 Django 項目環境終端

python3 manage.py shell

這個命令和 直接運行 python 進入 shell 的區別是:你能夠在這個 shell 裏面調用當前項目的 models.py 中的 API,對於操做數據的測試很是方便。

 

1.6.5 Django 項目環境終端

python3 manage.py dbshell

Django 會自動進入在settings.py中設置的數據庫,若是是 MySQL 或 postgreSQL,會要求輸入數據庫用戶密碼。

在這個終端能夠執行數據庫的SQL語句。若是您對SQL比較熟悉,可能喜歡這種方式。

1.6.6 更多命令

python3 manage.py                  #########切換到項目目錄下

查看全部的命令,忘記子名稱的時候特別有用。

 

1.6.7 靜態文件配置

概述:

 

     靜態文件交由Web服務器處理,Django自己不處理靜態文件。簡單的處理邏輯以下(以nginx爲例):

 

              URI請求-----> 按照Web服務器裏面的配置規則先處理,以nginx爲例,主要求配置在nginx.

                             conf裏的location

 

                         |---------->若是是靜態文件,則由nginx直接處理

 

                         |---------->若是不是則交由Django處理,Django根據urls.py裏面的規則進行匹配

 

    以上是部署到Web服務器後的處理方式,爲了便於開發,Django提供了在開發環境的對靜態文件的處理機制,方法是這樣:

 
概述

static配置:

STATIC主要指的是如css,js,images這樣文件:

STATIC_URL = '/static/'      # 別名

STATICFILES_DIRS = (

            os.path.join(BASE_DIR,"static"),  #實際名 ,即實際文件夾的名字

        )

 

'''

 

注意點1:

 django對引用名和實際名進行映射,引用時,只能按照引用名來,不能按實際名去找

        <script src="/statics/jquery-3.1.1.js"></script>

        ------error-----不能直接用,必須用STATIC_URL = '/static/':

        <script src="/static/jquery-3.1.1.js"></script>

 

注意點2:

 STATICFILES_DIRS = (

    ("app01",os.path.join(BASE_DIR, "app01/statics")),

        )

 

 <script src="/static/app01/jquery.js"></script>

 

'''
View Code

have a try

http://127.0.0.1:8000/static/jquery.js

media配置:

# in settings:

 

MEDIA_URL="/media/"

MEDIA_ROOT=os.path.join(BASE_DIR,"app01","media","upload")

 

# in urls:

from django.views.static import serve

url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
View Code

have a try:

http://127.0.0.1:8000/media/1.png
'''

        靜態文件的處理又包括STATIC和MEDIA兩類,這每每容易混淆,在Django裏面是這樣定義的:

       

        MEDIA:指用戶上傳的文件,好比在Model裏面的FileFIeld,ImageField上傳的文件。若是你定義

       

        MEDIA_ROOT=c:\temp\media,那麼File=models.FileField(upload_to="abc/")#,上傳的文件就會被保存到c:\temp\media\abc

 

        eg:

            class blog(models.Model):

                   Title=models.charField(max_length=64)

                   Photo=models.ImageField(upload_to="photo")

          上傳的圖片就上傳到c:\temp\media\photo,而在模板中要顯示該文件,則在這樣寫

          在settings裏面設置的MEDIA_ROOT必須是本地路徑的絕對路徑,通常是這樣寫:

                 BASE_DIR= os.path.abspath(os.path.dirname(__file__))

                 MEDIA_ROOT=os.path.join(BASE_DIR,'media/').replace('\\','/')

 

        MEDIA_URL是指從瀏覽器訪問時的地址前綴,舉個例子:

            MEDIA_ROOT=c:\temp\media\photo

            MEDIA_URL="/data/"

        在開發階段,media的處理由django處理:

 

           訪問http://localhost/data/abc/a.png就是訪問c:\temp\media\photo\abc\a.png

 

           在模板裏面這樣寫<img src="/media/abc/a.png">

 

           在部署階段最大的不一樣在於你必須讓web服務器來處理media文件,所以你必須在web服務器中配置,

           以便能讓web服務器能訪問media文件

           以nginx爲例,能夠在nginx.conf裏面這樣:

 

                 location ~/media/{

                       root/temp/

                       break;

                    }

 

           具體能夠參考如何在nginx部署django的資料。

          

          

           '''

 
View Code

第2章 視圖層之路由配置系統(views)

URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要爲該URL調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於這個URL調用這段代碼,對於那個URL調用那段代碼。

'''
    urlpatterns = [

         url(正則表達式, views視圖函數,參數,別名),

]

參數說明:

 

    一個正則表達式字符串

    一個可調用對象,一般爲一個視圖函數或一個指定視圖函數路徑的字符串

    可選的要傳遞給視圖函數的默認參數(字典形式)

    一個可選的name參數
'''

 

2.1 URLconf的正則字符串參數

2.1.1 簡單配置

######項目cms中的urls.py中的內容

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

]

 
項目cms中的urls.py中的內容
#############說明

'''

    NOTE:

    1 一旦匹配成功則再也不繼續

    2 若要從URL 中捕獲一個值,只須要在它周圍放置一對圓括號。

    3 不須要添加一個前導的反斜槓,由於每一個URL 都有。例如,應該是^articles 而不是 ^/articles。

    4 每一個正則表達式前面的'r' 是可選的可是建議加上。

 

一些請求的例子:

 

    /articles/2005/3/ 不匹配任何URL 模式,由於列表中的第三個模式要求月份應該是兩個數字。

    /articles/2003/ 將匹配列表中的第一個模式不是第二個,由於模式按順序匹配,第一個會首先測試是否匹配。

    /articles/2005/03/ 請求將匹配列表中的第三個模式。Django 將調用函數

                       views.month_archive(request, '2005', '03')。

    '''
說明
#設置項是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑

APPEND_SLASH=True

2.1.2 無名分組和有名分組(named group)

上面的示例使用簡單的、沒有命名的正則表達式組(經過圓括號)來捕獲URL 中的值並以位置 參數傳遞給視圖。在更高級的用法中,可使用命名的正則表達式組來捕獲URL 中的值並以關鍵字 參數傳遞給視圖。

 

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

下面是以上URLconf 使用命名組的重寫:

from app02 import views

from django.conf.urls import url

 

urlpatterns = [

  #無名分組

    url(r'^article/\d{4}', views.year) ,

 

    url(r'^article/(\d{4})$', views.year2),

    若是有多個匹配同樣的時候,誰放在上面就匹配誰,上面的就會把下面的覆蓋了

    正則加上括號,就是分組,會把分組的內容做爲year2函數的參數傳進去

    url(r'^article/(\d{4})/(\d{2})$', views.year_month),

 

    # 有名分組(就是給分組起個名字,這樣定義的好處就是按照關鍵字參數去傳參了,指名道姓的方式)

    url(r'^article/(?P<year>\d{4})/(?P<month>\d{2})$', views.year_month_hasname)

]

 
View Code

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

/articles/2005/03/   

請求將調用views.month_archive(request, year='2005', month='03')函數

/articles/2003/03/03/

請求將調用函數views.article_detail(request, year='2003', month='03', day='03')。

在實際應用中,這意味你的URLconf 會更加明晰且不容易產生參數順序問題的錯誤 —— 你能夠在你的視圖函數定義中從新安排參數的順序。固然,這些好處是以簡潔爲代價;有些開發人員認爲命名組語法醜陋而繁瑣。

 

2.1.3 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等等 —— 都將路由到相同的函數。

 

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

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

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

views.year_archive() 的year 參數將是一個字符串

 

2.1.5 指定視圖參數的默認值

有一個方便的小技巧是指定視圖參數的默認值。 下面是一個URLconf 和視圖的示例:

# URLconf

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

]

 

# View (in blog/views.py)

def page(request, num="1"):

 

    ...
View Code

在上面的例子中,兩個URL模式指向同一個視圖views.page —— 可是第一個模式不會從URL 中捕獲任何值。若是第一個模式匹配,page() 函數將使用num參數的默認值"1"。若是第二個模式匹配,page() 將使用正則表達式捕獲的num 值。

 

2.1.6 Including other URLconfs

#At any point, your urlpatterns can 「include」 other URLconf modules. This

#essentially 「roots」 a set of URLs below other ones.

 

#For example, here’s an excerpt of the URLconf for the Django website itself.

#It includes a number of other URLconfs:

 

 

from django.conf.urls import include, url

 

urlpatterns = [

   url(r'^admin/', admin.site.urls),

   url(r'^blog/', include('blog.urls')),

]

 
View Code

2.2 傳遞額外的選項給視圖函數(瞭解)

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')。

這個技術在Syndication 框架中使用,來傳遞元數據和選項給視圖。

2.3 URL 的反向解析

在使用Django 項目時,一個常見的需求是得到URL 的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用於處理服務器端的導航(重定向等)。

人們強烈但願不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 絕不相關的專門的URL 生成機制,由於這樣容易致使必定程度上產生過時的URL。

換句話講,須要的是一個DRY 機制。除了其它有點,它還容許設計的URL 能夠自動更新而不用遍歷項目的源代碼來搜索並替換過時的URL。

獲取一個URL 最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL 的其它必要的信息有視圖參數的類型(位置參數、關鍵字參數)和值。

Django 提供一個辦法是讓URL 映射是URL 設計惟一的地方。你填充你的URLconf,而後能夠雙向使用它:

l  根據用戶/瀏覽器發起的URL 請求,它調用正確的Django 視圖,並從URL 中提取它的參數須要的值。

l  根據Django 視圖的標識和將要傳遞給它的參數的值,獲取與之關聯的URL。

第一種方式是咱們在前面的章節中一直討論的用法。第二種方式叫作反向解析URL、反向URL 匹配、反向URL 查詢或者簡單的URL 反查。

在須要URL 的地方,對於不一樣層級,Django 提供不一樣的工具用於URL 反查:

l  在模板中:使用url 模板標籤。

l  在Python 代碼中:使用django.core.urlresolvers.reverse() 函數。

l  在更高層的與處理Django 模型實例相關的代碼中:使用get_absolute_url() 方法。

例子:

考慮下面的URLconf:

from django.conf.urls import url

 

from . import views

 

urlpatterns = [

    #...

    url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),

    #...

]

 
View Code

根據這裏的設計,某一年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.core.urlresolvers import reverse

from django.http import HttpResponseRedirect

 

def redirect_to_year(request):

    # ...

    year = 2006

    # ...

    return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

 
View Code

若是出於某種緣由決定按年歸檔文章發佈的URL應該調整一下,那麼你將只須要修改URLconf 中的內容。

在某些場景中,一個視圖是通用的,因此在URL 和視圖之間存在多對一的關係。對於這些狀況,當反查URL 時,只有視圖的名字還不夠。

 

2.4 名稱空間(Namespace)

命名空間(英語:Namespace)是表示標識符的可見範圍。一個標識符可在多個命名空間中定義,它在不一樣命名空間中的含義是互不相干的。這樣,在一個新的命名空間中可定義任何標識符,它們不會與任何已有的標識符發生衝突,由於已有的定義都處於其它命名空間中。

因爲name沒有做用域,Django在反解URL時,會在項目全局順序搜索,當查找到第一個name指定URL時,當即返回

咱們在開發項目時,會常用name屬性反解出URL,當不當心在不一樣的app的urls中定義相同的name時,可能會致使URL反解錯誤,爲了不這種事情發生,引入了命名空間。

 

project.urls:

urlpatterns = [

    url(r'^admin/', admin.site.urls),

    url(r'^app01/', include("app01.urls",namespace="app01")),

    url(r'^app02/', include("app02.urls",namespace="app02")),

]
View Code

app01.urls:

urlpatterns = [

    url(r'^index/', index,name="index"),

]

app02.urls:

urlpatterns = [

    url(r'^index/', index,name="index"),

]

app01.views 

from django.core.urlresolvers import reverse

 

def index(request):

 

    return  HttpResponse(reverse("app01:index"))

app02.views

from django.core.urlresolvers import reverse

 

def index(request):

 

    return  HttpResponse(reverse("app02:index"))
View Code

2.5 CBV

url(r'^login.html$', views.Login.as_view()),

 

============================

from django.views import View

class Login(View):

    

    def dispatch(self, request, *args, **kwargs):

        print('before')

        obj = super(Login,self).dispatch(request, *args, **kwargs)

        print('after')

        return obj

 

    def get(self,request):

       

        return render(request,'login.html')

 

    def post(self,request):

        print(request.POST.get('user'))

        return HttpResponse('Login.post')
View Code

第3章 視圖層之視圖函數(views)

一個視圖函數,簡稱視圖,是一個簡單的Python 函數,它接受Web請求而且返回Web響應。響應能夠是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片. . . 是任何東西均可以。不管視圖自己包含什麼邏輯,都要返回響應。代碼寫在哪裏也無所謂,只要它在你的Python目錄下面。除此以外沒有更多的要求了——能夠說「沒有什麼神奇的地方」。爲了將代碼放在某處,約定是將視圖放置在項目或應用程序目錄中的名爲views.py的文件中。

3.1 一個簡單的視圖

3.1.1 實例一

下面是一個返回當前日期和時間做爲HTML文檔的視圖:

from django.http 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)

 
View Code

讓咱們逐行閱讀上面的代碼:

l  首先,咱們從 django.http模塊導入了HttpResponse類,以及Python的datetime庫。

l  接着,咱們定義了current_datetime函數。它就是視圖函數。每一個視圖函數都使用HttpRequest對象做爲第一個參數,而且一般稱之爲request。

l  注意,視圖函數的名稱並不重要;不須要用一個統一的命名方式來命名,以便讓Django識別它。咱們將其命名爲current_datetime,是由於這個名稱可以精確地反映出它的功能。

l  這個視圖會返回一個HttpResponse對象,其中包含生成的響應。每一個視圖函數都負責返回一個HttpResponse對象。

 

3.1.2 實例二

######################views.py###############################

from django.shortcuts import render,HttpResponse

 

# Create your views here.

def year(request):  # request參數請求全部的參數,這個參數必定要有

    return HttpResponse("ok")  #每個視圖函數必須有return

def year2(request,year):

    print(year)

    return HttpResponse("hello")   #返回的必定是一個字符串,若是你想return純字符串,就用HttpResponse方法

def year_month(request,year,month):

    print(year,month)

    # 返回的是匹配的年和月拼接的結果

    return HttpResponse(year+month)   #

def year_month_hasname(request,month,year):

    # return HttpResponse("ok")

    print(year,month)

    return HttpResponse("month是:%s,year是:%s"%(month,year))

 
views.py

注意:視圖會返回一個HttpResponse對象,其中包含生成的響應。每一個視圖函數都負責返回一個HttpResponse對象。

3.2 HttpRequest對象的屬性和方法

3.2.1 HttpRequest對象的屬性

屬性:

  django將請求報文中的請求行、首部信息、內容主體封裝成 HttpRequest 類中的屬性。

   除了特殊說明的以外,其餘均爲只讀的。

 

'''

 

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.REQUEST

 

  一個相似於字典的對象,它首先搜索POST,而後搜索GET,主要是爲了方便。靈感來自於PHP 的 $_REQUEST。

 

  例如,若是 GET = {"name": "john"}  而 POST = {"age": '34'} , REQUEST["name"]  將等於"john", REQUEST["age"]  將等於"34"。

 

  強烈建議使用 GET 和 POST 而不要用REQUEST,由於它們更加明確。

 

 

 

8.HttpRequest.COOKIES

 

  一個標準的Python 字典,包含全部的cookie。鍵和值都爲字符串。

 

 

 

9.HttpRequest.FILES

 

  一個相似於字典的對象,包含全部的上傳文件信息。

   FILES 中的每一個鍵爲<input type="file" name="" /> 中的name,值則爲對應的數據。

 

  注意,FILES 只有在請求的方法爲POST 且提交的<form> 帶有enctype="multipart/form-data" 的狀況下才會

   包含數據。不然,FILES 將爲一個空的相似於字典的對象。

 

 

 

10.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 鍵。

 

 

11.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。

 

 

 

12.HttpRequest.session

 

   一個既可讀又可寫的相似於字典的對象,表示當前的會話。只有當Django 啓用會話的支持時纔可用。

    完整的細節參見會話的文檔。

 

 

13.HttpRequest.resolver_match

 

  一個 ResolverMatch 的實例,表示解析後的URL。這個屬性只有在 URL 解析方法以後才設置,這意味着它在全部的視圖中能夠訪問,

   可是在 URL 解析發生以前執行的中間件方法中不能夠訪問(好比process_request,但你可使用 process_view 代替)。

'''

 
View Code

3.2.2 HttpRequest對象的方法

'''

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.build_absolute_uri(location)

 

  返回location 的絕對URI。若是location 沒有提供,則使用request.get_full_path()的返回值。

 

  若是URI 已是一個絕對的URI,將不會修改。不然,使用請求中的服務器相關的變量構建絕對URI。

 

  例如:"http://example.com/music/bands/the_beatles/?print=true"

 

 

 

4.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

        複製代碼

        

 

 

 

5.HttpRequest.is_secure()

 

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

 

 

 

6.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') 裝飾你的視圖以讓響應可以正確地緩存。

 

 

 

7.HttpRequest.read(size=None)

 

  像文件同樣讀取請求報文的內容主體,一樣的,還有如下方法可用。

 

  HttpRequest.readline()

 

  HttpRequest.readlines()

 

  HttpRequest.xreadlines()

 

  其行爲和文件操做中的同樣。

 

  HttpRequest.__iter__():說明可使用 for 的方式迭代文件的每一行。'''

 
View Code

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

request.POST.getlist("hobby")

3.3 render 函數

render(request, template_name[, context])

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

參數:

     request: 用於生成響應的請求對象。

     template_name:要使用的模板的完整名稱,可選的參數

     context:添加到模板上下文的一個字典。默認是一個空字典。若是字典中的某個值是可調用的,視圖將在渲染模板以前調用它。

     content_type:生成的文檔要使用的MIME類型。默認爲DEFAULT_CONTENT_TYPE 設置的值。

     status:響應的狀態碼。默認爲200。

3.4 redirect 函數

參數能夠是:

l  一個模型:將調用模型的get_absolute_url() 函數

l  一個視圖,能夠帶有參數:將使用urlresolvers.reverse 來反向解析名稱

l  一個絕對的或相對的URL,將原封不動的做爲重定向的位置。

默認返回一個臨時的重定向;傳遞permanent=True 能夠返回一個永久的重定向。

示例:

你能夠用多種方式使用redirect() 函數。

 

3.4.1 傳遞一個對象

將調用get_absolute_url() 方法來獲取重定向的URL:

from django.shortcuts import redirect

 

def my_view(request):

    ...

    object = MyModel.objects.get(...)

    return redirect(object)
View Code

3.4.2 傳遞一個視圖的名稱

能夠帶有位置參數和關鍵字參數;將使用reverse() 方法反向解析URL: 

def my_view(request):

    ...

    return redirect('some-view-name', foo='bar')

3.4.3 傳遞要重定向的一個硬編碼的URL

def my_view(request):

    ...

    return redirect('/some/url/')

也能夠是一個完整的URL:

def my_view(request):

    ...

    return redirect('http://example.com/')

默認狀況下,redirect() 返回一個臨時重定向。以上全部的形式都接收一個permanent 參數;若是設置爲True,將返回一個永久的重定向:

def my_view(request):

    ...

    object = MyModel.objects.get(...)

    return redirect(object, permanent=True)  

3.4.4 跳轉(重定向)應用

-----------------------------------url.py

 

 url(r"login",   views.login),

 url(r"yuan_back",   views.yuan_back),

 

-----------------------------------views.py

def login(req):

    if req.method=="POST":

        if 1:

            # return redirect("/yuan_back/")

            name="yuanhao"

 

            return render(req,"my backend.html",locals())

 

    return render(req,"login.html",locals())

 

 

def yuan_back(req):

 

    name="苑昊"

 

    return render(req,"my backend.html",locals())

 

-----------------------------------login.html

 

<form action="/login/" method="post">

    <p>姓名<input type="text" name="username"></p>

    <p>性別<input type="text" name="sex"></p>

    <p>郵箱<input type="text" name="email"></p>

    <p><input type="submit" value="submit"></p>

</form>

-----------------------------------my backend.html

<h1>用戶{{ name }}你好</h1>

 
View Code

redirect關鍵點:兩次請求過程,掌握流程。

注意:render和redirect的區別:

一、 if 頁面須要模板語言渲染,須要的將數據庫的數據加載到html,那麼render方法則不會顯示這一部分。

二、 the most important: url沒有跳轉到/yuan_back/,而是還在/login/,因此當刷新後又得從新登陸。

 

第4章 模板層(template)

python的模板:HTML代碼+模板語法

模版包括在使用時會被值替換掉的 變量,和控制模版邏輯的 標籤

def current_time(req):

    # ================================原始的視圖函數

    # import datetime

    # now=datetime.datetime.now()

    # html="<html><body>如今時刻:<h1>%s.</h1></body></html>" %now

 

 

    # ================================django模板修改的視圖函數

    # from django.template import Template,Context

    # now=datetime.datetime.now()

    # t=Template('<html><body>如今時刻是:<h1>{{current_date}}</h1></body></html>')

    # #t=get_template('current_datetime.html')

    # c=Context({'current_date':str(now)})

    # html=t.render(c)

    #

    # return HttpResponse(html)

 

 

    #另外一種寫法(推薦)

    import datetime

    now=datetime.datetime.now()

    return render(req, 'current_datetime.html', {'current_date':str(now)[:19]})
View Code

模板語法:目的是將變量(數據庫的內容)如何巧妙的嵌入到html頁面中(就不用以前咱們用的字符串拼接了)

在 Django 模板中遍歷複雜數據結構的關鍵是句點字符  .

語法:

{{var_name}} 

4.1 示例

#####################view.py##############################

def index(request):

    import datetime

    s="hello"

    l=[111,222,333]    # 列表

    dic={"name":"yuan","age":18}  # 字典

    date = datetime.date(1993, 5, 2)   # 日期對象

 

    class Person(object):

        def __init__(self,name):

            self.name=name

 

    person_yuan=Person("yuan")  # 自定義類對象

    person_egon=Person("egon")

    person_alex=Person("alex")

 

    person_list=[person_yuan,person_egon,person_alex]

 

 

    return render(request,"index.html",{"l":l,"dic":dic,"date":date,"person_list":person_list}) 
view.py 

template

<h4>{{s}}</h4>

<h4>列表:{{ l.0 }}</h4>

<h4>列表:{{ l.2 }}</h4>

<h4>字典:{{ dic.name }}</h4>

<h4>日期:{{ date.year }}</h4>

<h4>類對象列表:{{ person_list.0.name }}</h4>
View Code

注意:句點符也能夠用來引用對象的方法(無參數方法)。

<h4>字典:{{ dic.name.upper }}</h4>

4.2 小練習

需求:當用戶輸入一個URL:  http://127.0.0.1:8080/timer,就返回給用戶一個當前的時間

基本流程

4.2.1 對urls進行一個設置

 

4.2.2 views.py

 

4.2.3 在template裏建立一個timer.html頁面

 

第5章 Django框架之第二篇反向解析

5.1 知識點回顧

5.1.1 MTV模型

  model:模型,和數據庫相關的

  template:模板,存放html文件,模板語法(目的是將變量如何巧妙的嵌入到HTML頁面中)。

  views:視圖函數

另加urls:url路徑與視圖函數的映射關係,,能夠不是一一對應的。

 

5.1.2 相關的一些命令

  建立一個Django項目:django-admin  startproject  projectname

  建立一個項目下的應用:python3  manage.py  startapp  appname

  運行:python3  manage.py  runserver  IP PORT

 

5.1.3 url配置(URLconf)urls.py

  功能:創建起url與視圖函數的映射關係

  url(正則表達式(規則),視圖函數,[可選參數])

   url:http://127.0.0.1:8080/blog/articles/2003/05?a=1&b=2

    匹配字符串:用戶輸入的url對應的路徑    /blog/articles/2003/05

注意:

  (1)出現覆蓋現象的狀況,也就是匹配規則衝突的時候,匹配第一個url

  (2)無名分組:url(r'^articles/(\d{4})/(\d{2})$', views.year_month),  # year(requset,1990,12)   按位置傳參數

  (3)有名分組:url(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})$', views.year_month),  # year(requset,year=1990,month=12)   按位置傳參數

  (4)url分發:url(r'^blog/',include('blog.urls'))

 

5.2 視圖函數的補充

5.2.1 視圖函數

一、視圖函數:必定是要包含兩個對象的(render源碼裏面有HttpResponse對象)

       request對象:-----》全部的請求信息

       HttpResponse:-----》響應的內容(字符串)

5.2.2 get請求發送數據

二、get請求發送數據:http://127.0.0.1:8000/login.html?user=asd&pwd=asd

重點:request裏包含哪些數據
1、request.GET: GET請求的數據,若是沒有數據是一個空字典    {}
2、request.POST:POST請求的數據 ,若是沒有數據是一個空字典  {}
3、request.method:請求方式:GET 或 POST
四、請求某個鍵下多個值時:request.POST.getlist("hobby")
5、 request.path : 請求路徑(只會拿到路徑,不拿數據)    

 請求url:http://127.0.0.1:8000/index.html/23?a=1
 path:request.path:/index.html/23
6、request.get_full_path():請求路徑(路徑和數據都會拿到)
  請求url:http://127.0.0.1:8000/index.html/23?a=1
  request.get_full_path():/index.html/23?a=1

5.3 render函數和redirect函數的區別

render:只會返回頁面內容,可是未發送第二次請求

redirect:發揮了第二次請求,url更新

 

 

 

具體實例說明以下:

5.3.1 render:

 

5.3.2 redirect:

 

5.4 反向解析

5.4.1 介紹

在使用Django 項目時,一個常見的需求是得到URL 的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用於處理服務器端的導航(重定向等)。

人們強烈但願不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 絕不相關的專門的URL 生成機制,由於這樣容易致使必定程度上產生過時的URL。

換句話講,須要的是一個DRY 機制。除了其它有點,它還容許設計的URL 能夠自動更新而不用遍歷項目的源代碼來搜索並替換過時的URL。

獲取一個URL 最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL 的其它必要的信息有視圖參數的類型(位置參數、關鍵字參數)和值。

Django 提供一個辦法是讓URL 映射是URL 設計惟一的地方。你填充你的URLconf,而後能夠雙向使用它:

l  根據用戶/瀏覽器發起的URL 請求,它調用正確的Django 視圖,並從URL 中提取它的參數須要的值。

l  根據Django 視圖的標識和將要傳遞給它的參數的值,獲取與之關聯的URL。

 

第一種方式是咱們在前面的章節中一直討論的用法。第二種方式叫作反向解析URL、反向URL 匹配、反向URL 查詢或者簡單的URL 反查。

在須要URL 的地方,對於不一樣層級,Django 提供不一樣的工具用於URL 反查:

l  在模板中:使用url 模板標籤。

l  在Python 代碼中:使用django.core.urlresolvers.reverse() 函數。

l  在更高層的與處理Django 模型實例相關的代碼中:使用get_absolute_url() 方法。

5.4.2 例子:

考慮下面的URLconf:

from django.conf.urls import url

 

from . import views

 

urlpatterns = [

    #...

    url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),

    #...

]

 
View Code

根據這裏的設計,某一年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>

 
View Code

在Python 代碼中,這樣使用:

from django.core.urlresolvers import reverse

from django.http import HttpResponseRedirect

 

def redirect_to_year(request):

    # ...

    year = 2006

    # ...

    return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
View Code

若是出於某種緣由決定按年歸檔文章發佈的URL應該調整一下,那麼你將只須要修改URLconf 中的內容。

在某些場景中,一個視圖是通用的,因此在URL 和視圖之間存在多對一的關係。對於這些狀況,當反查URL 時,只有視圖的名字還不夠。

 

5.4.3 例子分析

例子中:

分析:想咱們一開始寫的硬編碼,也就是吧action要跳轉的路徑寫死了。可是像淘寶,天貓等都會常常更新新東西,,那麼你的頁面上的url路徑也會時不時的變化。可是若是有特別多的商品,那麼你就得去服務端一個一個的改,這樣顯得很麻煩,那麼有沒有一種機制幫咱們解決問題呢?那就按照我下面的辦法解決。就把url路徑寫活了。

一、首先給url起一個別名。

二、而後在login.html中寫上{%  url ‘別名’’  %}    ,若是在頁面中點擊查看元素,它會變成login.html,,,固然個人是分發了,,就會變成test/login.html

三、這樣你就能夠修改你的正則了,,由於他是按照別名走的,不會影響。

 

urls.py

 

login.html

 

查看元素的結果:

 

這樣的好處是:不管你怎麼改你要匹配的url,只要你寫上了別名。在html實現了模板語法,就會去找別名對應的那個url,之後無論你怎麼改url都沒事,就寫活了,就不像一開始寫的硬編碼了。

 

第6章 Django框架之第三篇模板語法

6.1 什麼是模板?

只要是在html裏面有模板語法就不是html文件了,這樣的文件就叫作模板。

 

6.2 模板語法分類

6.2.1 模板語法之變量:語法爲 {{ }}:

在 Django 模板中遍歷複雜數據結構的關鍵是句點字符  .(也就是點)

 

views.py

def index(request):

    name = "hello haiyan"

    i = 200

    l = [11,22,33,44,55]

    d = {"name":"haiyan","age":20}

 

    class People(object): #繼承元類

        def __init__(self,name,age):

            self.name = name

            self.age = age

        def __str__(self):

            return self.name+str(self.age)

        def dream(self):

            return "你有夢想嗎?"

    #實例化

    person_egon = People("egon",10)

    person_dada = People("dada",34)

    person_susan = People("susan",34)

    person_list = [person_dada,person_egon,person_susan]

 

    return render(request,"index.html",

                    {

                        "name":name,

                        "i":i,

                        "l":l,

                        "d":d,  #鍵對應的是模板裏的名字。值對應的是上面定義的變量

                        "person_egon":person_egon,

                        "person_dada":person_dada,

                        "person_list":person_list,

                    }

              )

    # return render(request,"index.html",locals())

    #用locals()能夠不用寫上面的render了。不過用locals(),views裏面用什麼名。模板裏面就得用什麼名

    # locals()局部的:用了locals就至關於都得按照上面的那樣

 
View Code

 

template/index.html

<h4>變量{{ z }}:深度查詢</h4><hr>

<h3>{{ name }}</h3>

<p>{{ i }}</p>

<p>{{ l }}</p>

<p>{{ d }}</p>

<p>{{ l.0 }}------》取單個值可經過句點符(也就是點)</p>

<p>{{ l.4 }}</p>

<p>{{ d.name }}</p>

<p>{{ d.age }}-----》字典也能夠根據句點符取值,一個點就搞定了。

然而在前端頁面中是看不到你的模板語法的,當你點擊審查元素的

時候,你就會發現,偷偷的換過來了</p>

<p>{{ person_dada.name }}</p>

<p>{{ person_egon.age }}</p>

<p>{{ person_dada.dream }}</p>  <!-- .方法的時候,注意當前的dream方法是沒有參數的-->

<p>{{ person_list.2 }}</p>  <!--單個取值-->

<p>{{ person_list.1.name }}</p>

<!-- 那怎麼讓對象變成字符串呢?在index視圖函數裏裏面再加上一個__str__內置方法-->

<!--__str__是對象字符串的改變-->

 
View Code

注意:句點符也能夠用來引用對象的方法(無參數方法)。

<h4>字典:{{ dic.name.upper }}</h4>

6.2.2 模板語法之標籤:語法爲 {% tag  %}:

標籤看起來像是這樣的: {% tag %}。標籤比變量更加複雜:一些在輸出中建立文本,一些經過循環或邏輯來控制流程,一些加載其後的變量將使用到的額外信息到模版中。

一些標籤須要開始和結束標籤 (例如{% tag %} ...標籤 內容 ... {% endtag %})。

 

1for標籤(注:循環序號能夠經過{{forloop}}顯示)

<h3>循環取值1</h3><hr>

{% for item in person_list %}

    <p>{{ item.name }},{{ item.age }}</p>

{% endfor %}

 

<h3>循環取值2:倒序</h3><hr>

{% for item in person_list reversed %}

    <!--序號從1開始-->

    <p>{{ forloop.counter }}----->{{ item.name }},{{ item.age }}</p>

    <!--序號從0開始--><p>{{ forloop.counter0 }}----->{{ item.name }},{{ item.age }}</p><!-- 序號倒序 --><p>{{ forloop.revcounter }}----->{{ item.name }},{{ item.age }}</p>

{% endfor %}

 

<h3>循環取值3:字典</h3><hr>

{% for k,v in d.items %}

    <p>{{ k }},{{ v}}</p>

{% endfor %}

 
View Code

2、for....empty for 標籤帶有一個可選的{% empty %} 從句,以便在給出的組是空的或者沒有被找到時,能夠有所操做。

{% for person in person_list %}

    <p>{{ person.name }}</p>

 

{% empty %}

    <p>sorry,no person here</p>

{% endfor %}
View Code

3、if標籤 :{% if %}會對一個變量求值,若是它的值是「True」(存在、不爲空、且不是boolean類型的false值),對應的內容塊會輸出。

{% if i > 300 %}

    <p>大於{{ i }}</p>

{% elif i == 200  %}

    <p>等於{{ i }}</p>

{% else %}

    <p>小於{{ i }}</p>

{% endif %}
View Code

4、with:使用一個簡單地名字緩存一個複雜的變量,當你須要使用一個「昂貴的」方法(好比訪問數據庫)不少次的時候是很是有用的

{% with total=business.employees.count %}

    {{ total }} employee{{ total|pluralize }}

{% endwith %}

 

<p>{{ person_list.2.name }}</p>

{% with name=person_list.2.name %}

    <p>{{ name }}</p>

{% endwith %}
View Code

5、csrf_token:這個標籤用於跨站請求僞造保護

提交數據的時候就會作安全機制,當你點擊提交的時候會出現一個forbbiddon的錯誤,就是用setting配置裏的scrf作安全機制的,那麼咱們能夠把它給註釋了,或者在form表單下面添加一個{% csrf_token %}   ,這纔是真正解決的辦法,註釋不是解決的辦法

<h3>scrf_token</h3><form action="/tag/" method="post">

    {% csrf_token %}

    <p><input type="text" name="haiyan"></p>

    <input type="submit">

</form>
View Code

6.2.3 模板語法之過濾器:語法 {{obj|filter__name:param}}

一、default:若是一個變量是false或者爲空,使用給定的默認值。不然,使用變量的值。例如:

<p>default過濾器:{{ li|default:"若是顯示爲空,設置的解釋性的內容" }}</p>

2、length:返回值的長度。它對字符串和列表都起做用。例如:

{{ value|length }}

若是 value 是 ['a', 'b', 'c', 'd'],那麼輸出是 4。

 

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

{{ value|filesizeformat }}

若是 value 是 123456789,輸出將會是 117.7 MB。  

 

4、date:若是 value=datetime.datetime.now()

{{ value|date:"Y-m-d" }}  

5、slice  :切片

若是 value="hello world"

{{ value|slice:"2:-1" }}

6truncatechars  截斷

若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。

參數:要截斷的字符數

例如:

<p>截斷字符:{{ content|truncatechars:20 }}</p>

<p>截斷單詞:{{ content|truncatewords:4 }}</p>

若是content是「I am is haiyan,how are you asd df dfgfdgdg?

輸出結果: 截斷字符:I am is haiyan,ho...

輸出結果 :截斷單詞:I am is haiyan,how ...

 

7safe

Django的模板中會對HTML標籤和JS等語法標籤進行自動轉義,緣由顯而易見,這樣是爲了安全。可是有的時候咱們可能不但願這些HTML元素被轉義,好比咱們作一個內容管理系統,後臺添加的文章中是通過修飾的,這些修飾多是經過一個相似於FCKeditor編輯加註了HTML修飾符的文本,若是自動轉義的話顯示的就是保護HTML標籤的源文件。爲了在Django中關閉HTML的自動轉義有兩種方式,若是是一個單獨的變量咱們能夠經過過濾器「|safe」的方式告訴Django這段代碼是安全的沒必要轉義。好比:

value="<a href="">點擊</a>"

 

{{ value|safe}}

<p>{{ label }}</p>  <!--爲了安全系統會把標籤變成字符串-->

<p>{{ label|safe }}</p>    <!--加上safe,肯定你的數據是安全的才能被當成是標籤-->

這裏簡單介紹一些經常使用的模板的過濾器,更多詳見

 

6.2.4 自定義標籤和過濾器

1、在settings中的INSTALLED_APPS配置當前app,否則django沒法找到自定義的simple_tag.

2、在app中建立templatetags模塊(模塊名只能是templatetags)

3、在templatetags裏面建立任意 .py 文件,

如:my_tags.py

from django import template

from django.utils.safestring import mark_safe

 

register = template.Library()   #register的名字是固定的,不可改變

@register.filter   過濾器
def multi(x,y):
    return x*y

@register.simple_tag  標籤
def multitag(x,y,z):
    return x*y*z

@register.simple_tag  標籤
def my_input(id,arg):
   result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
   return mark_safe(result)
View Code

4、在使用自定義simple_tagfilterhtml文件中導入以前建立的 my_tags.py

{% load my_tags %} 

5、使用simple_tagfilter(如何調用

過濾器: {{ var|filter_name:參數 }} # 參數只能是兩個,一個參數是變量var ,一個是參數是後面的那個參數

標籤: {% simple_tag 參數1 參數2 ... %}

-------------------------------.html

{% load xxx %} 

     

# num=12

{{ num|multi:2 }} #24

 

{{ num|multi:"[22,333,4444]" }}   至關於複製了,吧[22,333,4444]乘了num遍

{% multitag 2 5 6 %} 參數不限,但不能放在if for語句中 {% simple_tag_multi num 5 %}
View Code
自定義過濾器函數的參數只能兩個,能夠進行邏輯判斷
自定義標籤無參數限制,不能進行邏輯判斷
{% if i|multi:5 > 1000 %}   <!-- 判斷i*5>1000 -->

    <p>大於{{ i }}</p>

{% else %}

    <p>大於等於{{ i }}</p>

{% endif %}
View Code

第7章 Django框架之模板繼承和靜態文件配置

7.1 模板繼承

目的是:減小代碼的冗餘

語法:

{% block classinfo %}

 

{% endblock %}

7.1.1 具體步驟

一、建立一個base.html文件,
二、把要顯示的頁面的內容寫在這裏面,也就是html要在瀏覽器顯示的內容
三、在right裏面寫個盒子
  {% block classinfo %}

  {% endblock %}
在這裏面寫個空盒子,之後誰來擴展就在這個盒子裏面添加相應的內容就好了

四、而後再建立一個.html文件,讓這個繼承base.html文件,
  {% extends "base.html" %}    #必須是在文件的第一行
  在基板裏面添加內容
  {% block classinfo %}
    <h2>首頁</h2>
    <h2>學生信息</h2>
    <h3>{{ class_id }}班</h3>
  {% endblock%}

五、也能夠寫好多盒子,
  在left中寫個盒子
    {% block menu %}
      <p>I see you you</p>
    {% endblock %}

 

注意:

盒子裏面能夠有默認的內容,若是有默認的時候你不擴展就走默認的,若是你擴展了,就替換了,那麼不替換直接追加能夠嘛?能夠的,那就用下面的方式。

{% block.super %}

 

例如:

{% block menu %}

 

  {{ block.super }}

 

  <p>!!!</p>       #先繼承父類的,後插入數據

 

{% endblock %}
View Code

7.1.2 注意項

一、模板繼承圍繞兩點:繼承和擴展
          你有什麼繼承什麼,       
          擴展的是盒子,
二、模板中設置的盒子越多越好,由於這樣你想擴展的時候就容易了。我想擴展就擴展了。不擴展就不擴展了
三、爲了更好的可讀性,你也能夠給你的 {% endblock %} 標籤一個 名字 。例如:

{% block content %}

...

{% endblock content %}  

四、若是你發現你本身在大量的模版中複製內容,那可能意味着你應該把內容移動到父模版中的一個 {% block %} 中。

最後,請注意你並不能在一個模版中定義多個相同名字的 block 標籤。這個限制的存在是由於block標籤的做用是「雙向」的。這個意思是,block標籤不只提供了一個坑去填,它還在 _父模版_中定義了填坑的內容。若是在一個模版中有兩個名字同樣的 block 標籤,模版的父模版將不知道使用哪一個block的內容。

 

7.2 具體例子說明

7.2.1 urls.py

urlpatterns = [

    url(r'^admin/', admin.site.urls),

    url(r'^text/(\d+)', views.text),

]

7.2.2 views.py

from django.shortcuts import render,redirect

 

# Create your views here.

 

def text(request,class_id):

        # 班級變量

        print(class_id)  #拿到的是你在路徑裏輸入的幾就是幾

        # 數據庫查詢

        return render(request, "text.html", {"class_id": class_id})
View Code

7.2.3 templaite / base.html

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width">

    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">

    <title>Title</title>

    <style>

        .right {

            height: 400px;

            background-color: silver;

        }

    </style>

</head>

<body>

{#導航條#}

<nav class="navbar navbar-primary navbar-inverse">

    <div class="container-fluid">

        <!-- Brand and toggle get grouped for better mobile display -->

        <div class="navbar-header">

            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"

                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">

                <span class="sr-only">Toggle navigation</span>

                <span class="icon-bar"></span>

                <span class="icon-bar"></span>

                <span class="icon-bar"></span>

            </button>

            <a class="navbar-brand" href="#">Brand</a>

        </div>

 

        <!-- Collect the nav links, forms, and other content for toggling -->

        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">

            <ul class="nav navbar-nav">

                <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>

                <li><a href="#">Link</a></li>

                <li class="dropdown">

                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"

                       aria-expanded="false">Dropdown <span class="caret"></span></a>

                    <ul class="dropdown-menu">

                        <li><a href="#">Action</a></li>

                        <li><a href="#">Another action</a></li>

                        <li><a href="#">Something else here</a></li>

                        <li role="separator" class="divider"></li>

                        <li><a href="#">Separated link</a></li>

                        <li role="separator" class="divider"></li>

                        <li><a href="#">One more separated link</a></li>

                    </ul>

                </li>

            </ul>

        </div><!-- /.navbar-collapse -->

    </div><!-- /.container-fluid -->

</nav>

{#內容#}

<div class="containers">

    <div class="row">

        <div class="col-md-11 col-lg-offset-1">

            {#            左側#}

            <div class="left col-md-3">

                {% block menu %}

                    <div class="list-group">

                        <a href="#" class="list-group-item active">

                            學生班級

                        </a>

                        <a href="/text/6" class="list-group-item">s6</a>

                        <a href="/text/7" class="list-group-item">s7</a>

                        <a href="/text/8" class="list-group-item">s8</a>

                        <a href="/text/9" class="list-group-item">s9</a>

                    </div>

                {% endblock %}

            </div>

            {#            右側#}

            <div class="right col-md-8">

                {#                定義一個盒子#}

                {% block classinfo %}

 

                {% endblock %}

            </div>

        </div>

    </div>

</div>

{#底部#}

 

</body>

</html>
View Code

7.2.4 template /text.py   繼承上面的文件

{% extends "base.html" %}



{% block classinfo %}

    <h1>學生信息</h1>

    <h3>{{ class_id }}班級</h3>

{% endblock %}



{#追加#}

{% block menu %}

    {{ block.super }}

    <a href="">學生信息</a>

{% endblock %}
View Code

7.3 靜態文件配置

咱們本身導入的一些包就叫作靜態文件

一、在全局中先建立一個static的包,

二、在static裏面導入咱們的bootstrap,仍是jquery等

三、而後在settings.py中加上一些配置

STATIC_URL = '/static/'   #這個配置就至關於下面配置的別名,若是這裏的名字修改了就按照這裏的名字去導入

STATICFILES_DIRS = [

    os.path.join(BASE_DIR,"static")  #E:\day68\static 找到static路徑

]

 

四、導入css,js,jquery

<link rel = "stysheet",href= "/static/index.css/">

 

<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">

第8章 django之ORM數據庫操做

8.1 ORM介紹

映射關係:

  表名 --------------------》類名

  字段--------------------》屬性

  表記錄-----------------》類實例化對象

ORM的兩大功能:

  操做表:

    - 建立表

    - 修改表

    - 刪除表

  操做數據行:

    - 增刪改查

ORM利用pymysql第三方工具連接數據庫

Django沒辦法幫咱們建立數據庫,只能咱們建立完以後告訴它,讓django去連接

 

8.2 建立表以前的準備工做

1、本身建立數據庫

2、在settings裏面配置mysql數據庫連接

  sqlite3------改成mysql

# 修改django默認的數據庫的sqlite3爲mysql

DATABASES = {

    'default': {

            'ENGINE': 'django.db.backends.mysql', #經過這個去連接mysql

            'NAME': 'djangotsgl',

            'USER':'root',

            'PASSWORD':'123456',

            'HOST':'localhost',

            'PORT':'3306',

        }

    } 

 
View Code

這樣寫上之後django會默認的就去連接數據庫,這時你會看到報錯了,那麼解決的辦法就是下面的這樣。

 

3、app01中的--init--文件

import pymysql

pymysql.install_as_MySQLdb()

4、建立數據庫表

models.py

class Book(models.Model):  #必需要繼承的

    nid = models.AutoField(primary_key=True)  #自增id(能夠不寫,默認會有自增id)

    title = models.CharField(max_length=32)

    publishDdata = models.DateField()  #出版日期

    author = models.CharField(max_length=32)

    price = models.DecimalField(max_digits=5,decimal_places=2)  #一共5位,保留兩位小數

 
View Code

執行命令建立:(須要記住的!!!) 

python3 manage.py makemigrations   建立腳本

python3 manage.py migrate   遷移

8.3 具體例子實現

8.3.1 model.py

 

8.3.2 urls.py

 

8.3.3 views.py

 

8.3.4 template /index.html

#######################圖片內容具體#######################

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width">

    <title>Title</title>

    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">

    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>

    <style>

        table{

            margin-top: 50px;

        }

    </style>

</head>

<body>

<div class="containers">

    <div class="row">

        <div class="col-md-9 col-md-offset-2">

            <table class="table table-hover">

                <thead>

                    <tr>

                        <th>編號</th>

                        <th>書名</th>

                        <th>出版日期</th>

                        <th>做者</th>

                        <th>價錢</th>

                        <th>操做</th>

                    </tr>

                </thead>

                <tbody>

                {% for book in book_list %}

                    <tr>

                            <td>{{ book.nid }}</td>

                            <td>{{ book.title }}</td>

                            <td>{{ book.publishDdata|date:'Y-m-d' }}</td>

                            <td>{{ book.author }}</td>

                            <td>{{ book.price }}</td>

                            <td>

                                <a href="/del/{{ book.nid }}"><button class="btn btn-danger">刪除</button></a>

                                <a href="/edit/{{ book.nid }}"><button class="btn btn-success">編輯</button></a>

                                <a href="/add/"><button class="btn btn-primary">添加</button></a>

                            </td>

                    </tr>

                {% endfor %}

                </tbody>

            </table>

        </div>

    </div>

</div>

</body>

</html>

 
圖片內容具體

8.4 查看數據庫的sql語句

5、查看數據庫的sql語句(加在settings.py)

查看數據庫執行代碼

LOGGING = {

    'version': 1,

    'disable_existing_loggers': False,

    'handlers': {

        'console':{

            'level':'DEBUG',

            'class':'logging.StreamHandler',

        },

    },

    'loggers': {

        'django.db.backends': {

            'handlers': ['console'],

            'propagate': True,

            'level':'DEBUG',

        },

    }

}
View Code

第9章 Django之ORM數據庫操做注意細節

9.1 多對多的正反向查詢

class Class(models.Model):

    name = models.CharField(max_length=32,verbose_name="班級名")

    course = models.CharField(verbose_name="課程",max_length=32)

    def __str__(self):

        return self.name

 

class Teacher(models.Model):

    name = models.CharField(max_length=23,verbose_name="姓名")

    classes = models.ManyToManyField(verbose_name="所屬班級",to="Class")

    def __str__(self):

        return self.name
View Code

9.1.1 題目1:查找娜娜老師所帶的班級

# 方式一:基於對象的查找

        obj = models.Teacher.objects.filter(name="娜娜").first()

        print(obj.classes.all())

        print("娜娜老師帶的班級",obj.classes.values("name"))

        # 方式二:基於雙下劃線的查找

        obj_cls = models.Teacher.objects.filter(name="娜娜").values("classes__name")

        print("娜娜老師帶的班級",obj_cls)
View Code

注意:要說明的是多對多的查詢用.all,查單個的時候用.values或者values_list,不要用obj.classes.name,這樣查到的會是None,反向查詢也是如此。我就是犯了這樣的錯,引覺得戒。。

總結:無論是一對多,仍是多對多,要是查詢多得一方就得用all()

運行結果截圖:

 

表結構:

from django.db import models

 

# Create your models here.

# 一個學生有一個班級,一個班級能夠有好多學生,因此是

# 一對多的關係,關聯字段放在多的一方

class Student(models.Model):

    name = models.CharField(max_length=32,verbose_name="姓名")

    age = models.IntegerField(verbose_name="年齡")

    classes = models.ForeignKey(to="Class",verbose_name="所屬班級")

    def __str__(self):

        return self.name

 

class Class(models.Model):

    name = models.CharField(max_length=32,verbose_name="班級名")

    course = models.CharField(verbose_name="課程",max_length=32)

    def __str__(self):

        return self.name

 

class Teacher(models.Model):

    name = models.CharField(max_length=23,verbose_name="姓名")

    classes = models.ManyToManyField(verbose_name="所屬班級",to="Class")

    def __str__(self):

        return self.name

 
View Code

9.1.2 查詢海燕在那個班級

# 方式一:

    print("海燕所在的班級",models.Student.objects.filter(name="海燕").values("classes__name"))

    # 方式二:

    obj_cls = models.Student.objects.filter(name="海燕").first()

    print("海燕所在的班級",obj_cls.classes.name)

 
View Code

9.1.3 查詢海燕所在班的老師的姓名

print("海燕所在班的老師的姓名",models.Student.objects.filter(name="海燕").values("classes__teacher__name"))

9.1.4 查詢軟件測試151班的全部學生的姓名

print("軟件測試151班的全部學生的姓名",models.Class.objects.filter(name="軟件測試151").values("student__name"))

 obj = models.Class.objects.filter(name="軟件測試151").first()

 # print("軟件測試151班的全部學生的姓名",obj.student_set.name)  #這樣打印的結果是None

 print("軟件測試151班的全部學生的姓名",obj.student_set.all().values("name"))
View Code

9.2 須要掌握的一個很重要的知識點

一、form表單中要用submit,若是用button切記要加上type,否則button默認的type是submit,會有影響

  <button class="login" type="button">註冊</button>

 

<button type="button" onclick="doValidation();">提交</button>

<input type="button" onclick="doValidation();" value="提交"/>

上面兩種寫法是對的,功能同樣。

 

<button onclick="doValidation();">提交</button>

若是寫成這種,默認爲submit,原本doValidation方法裏有提交功能了,

再加上按鈕也是提交功能,會提交兩次。因此使用按鈕時最好指定type類型。

 
View Code

第10章 django之數據庫表的單表查詢

10.1 添加表記錄

對於單表有兩種方式

 # 添加數據的兩種方式

    # 方式一:實例化對象就是一條表記錄

    Frank_obj = models.Student(name ="海東",course="python",birth="2000-9-9",fenshu=80)

    Frank_obj.save()

    # 方式二:

    models.Student.objects.create(name ="海燕",course="python",birth="1995-5-9",fenshu=88)
View Code

10.2 查詢表記錄

10.2.1 查詢相關API

# 查詢相關API

    # 一、all():查看全部

    student_obj = models.Student.objects.all()

    print(student_obj)  #打印的結果是QuerySet集合

    # 二、filter():能夠實現且關係,可是或關係須要藉助Q查詢實現。。。

    #              查不到的時候不會報錯

    print(models.Student.objects.filter(name="Frank"))  #查看名字是Frank的

    print(models.Student.objects.filter(name="Frank",fenshu=80))  #查看名字是Frank的而且分數是80的

    # 三、get():若是找不到就會報錯,若是有多個值,也會報錯,只能拿有一個值的

    print(models.Student.objects.get(name="Frank"))  #拿到的是model對象

    print(models.Student.objects.get(nid=2))  #拿到的是model對象

    # 四、exclude():排除條件

    print( models.Student.objects.exclude(name="海東")) #查看除了名字是海東的信息

    # 五、values():是QuerySet的一個方法 (吧對象轉換成字典的形式了,)

    print(models.Student.objects.filter(name="海東").values("nid","course")) #查看名字爲海東的編號和課程

    #打印結果:<QuerySet [{'nid': 2, 'course': 'python'}, {'nid': 24, 'course': 'python'}]>

    # 六、values_list():是queryset的一個方法 (吧對象轉成元組的形式了)

    print(models.Student.objects.filter(name="海東").values_list("nid", "course"))

    #打印結果:< QuerySet[(2, 'python'), (24, 'python')] >

    # 七、order_by():排序

    print(models.Student.objects.all().order_by("fenshu"))

    # 八、reverse():倒序

    print(models.Student.objects.all().reverse())

    # 九、distinct():去重(只要結果裏面有重複的)

    print(models.Student.objects.filter(course="python").values("fenshu").distinct())

    # 十、count():查看有幾條記錄

    print(models.Student.objects.filter(name="海東").count())

 

    # 十一、first()

    # 十二、last()

    return render(request,"test.html",{"student_obj":student_obj})

    # 1三、esits:查看有沒有記錄,若是有返回True,沒有返回False

        #         並不須要判斷全部的數據,

        # if models.Book.objects.all().exists():
View Code

10.2.2 雙下劃線之單表查詢

models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 獲取id小於1 且 大於10的值

 

models.Tb1.objects.filter(id__in=[11, 22, 33])   # 獲取id等於十一、2二、33的數據

models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

 

models.Tb1.objects.filter(name__contains="ven")  #包括ven的

models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感

 

models.Tb1.objects.filter(id__range=[1, 2])      # 範圍bettwen and

 

startswith,istartswith, endswith, iendswith 
View Code
對象能夠調用本身的屬性,用一個點就能夠

還能夠經過雙下劃線。。。

    models.Book.objects.filter(price__gt=100)   價格大於100的書

    models.Book.objects.filter(author__startwith= "")    查看做者的名字是以張開頭的

    主鍵大於5的且小於2

    price__gte=99大於等於

    publishDate__year =2017,publishDate__month = 10   查看2017年10月份的數據

10.3 修改表記錄

 

注意:

<1> 第二種方式修改不能用get的緣由是:update是QuerySet對象的方法,get返回的是一個model對象,它沒有update方法,而filter返回的是一個QuerySet對象(filter裏面的條件可能有多個條件符合,好比name='alvin',可能有兩個name='alvin'的行數據)。

<2>在「插入和更新數據」小節中,咱們有提到模型的save()方法,這個方法會更新一行裏的全部列。 而某些狀況下,咱們只須要更新行裏的某幾列。

 

此外,update()方法對於任何結果集(QuerySet)均有效,這意味着你能夠同時更新多條記錄update()方法會返回一個整型數值,表示受影響的記錄條數。

注意,這裏由於update返回的是一個整形,因此無法用query屬性;對於每次建立一個對象,想顯示對應的raw sql,須要在settings加上日誌記錄部分

 

10.4 刪除表記錄

刪除方法就是 delete()。它運行時當即刪除對象而不返回任何值。例如:e.delete()

def delstudent(request,id):

    # 刪除數據

    models.Student.objects.filter(nid=id).delete()

    return redirect("/test/")

你也能夠一次性刪除多個對象。每一個 QuerySet 都有一個 delete() 方法,它一次性刪除 QuerySet 中全部的對象。

例如,下面的代碼將刪除 pub_date 是2005年的 Entry 對象:

Entry.objects.filter(pub_date__year=2005).delete()

要牢記這一點:不管在什麼狀況下,QuerySet 中的 delete() 方法都只使用一條 SQL 語句一次性刪除全部對象,而並非分別刪除每一個對象。若是你想使用在 model 中自定義的 delete() 方法,就要自行調用每一個對象的delete 方法。(例如,遍歷 QuerySet,在每一個對象上調用 delete()方法),而不是使用 QuerySet 中的 delete()方法。

在 Django 刪除對象時,會模仿 SQL 約束 ON DELETE CASCADE 的行爲,換句話說,刪除一個對象時也會刪除與它相關聯的外鍵對象。例如:

b = Blog.objects.get(pk=1)

# This will delete the Blog and all of its Entry objects.

b.delete()

要注意的是: delete() 方法是 QuerySet 上的方法,但並不適用於 Manager 自己。這是一種保護機制,是爲了不意外地調用 Entry.objects.delete() 方法致使 全部的 記錄被誤刪除。若是你確認要刪除全部的對象,那麼你必須顯式地調用:

Entry.objects.all().delete()

10.5 編輯表格中的內容的涉及到的語法

編輯操做涉及到的語法

 

分析:

    1、點擊編輯,讓跳轉到另外一個頁面,拿到我點擊的那一行

    兩種取id值的方式

    方式一:

        利用數據傳參數(做爲數據參數傳過去了)

        <a href="/edit/?book_id = {{book_obj.nid}}"></a>  #至關於發了一個鍵值對

        url裏面就不用寫匹配的路徑了,

        id = request.GET.get("book_id")  #取值

   

    方式二:

        利用路徑傳參,得在url裏面加上(\d+),就得給函數傳個參數,無名分組從參數裏面取值

        <a href="/{{book_obj.nid}}"></a>

   

    2、拿到id,而後在作篩選

        id = request.GET.get("book_id")

        book_obj = models.Book.objects.filter(nid=id)  #拿到的是一個列表對象

        注意:

            1.取[0]就拿到對象了,,而後對象.屬性就能夠取到值了

            2.用get,你取出來的數據必須只有一條的時候,,若是有多條用get就會報錯,,,可是用get就不用加[0]了

        book_obj = models.Book.objects.filter(nid=id)[0]   

       

    3、當點擊編輯的時候怎麼讓input框裏顯示文本內容

        value = "{{book_obj.title}}"

    4、改完數據後從新提交

        當提交的時候走action...../edit/}

        隱藏一個input,

        <input type="hidden" name = "book_id" value="{{book_obj.nid}}">

        判斷post的時候:

            修改數據

                方式一:save(這種方式效率是很是低的,不推薦使用,瞭解就好了)

                    修改的前提是先取(拿到要編輯的id值)

                    id = request.POST.get("book_id")

                    bk_obj = models.Book.objects.filter(nid=id)[0]

                    bk_obj.title = "hhhhhh"  #這是寫死了,不能都像這樣寫死了

                    bk_obj.save()  只要是用對象的這種都要.save

                方式二:update

                title = request.POST.get("title")

                models.Book.objects.filter(nid=id).update(title=title,......)

            跳轉到index

           

           

           

           

若是是post請求的時候怎麼找到id呢,

1、若是是數據傳參:(也就是get請求的時候)

    能夠經過一個隱藏的input框,給這個框給一個name屬性,value屬性。經過request.POST.get(""),,就能夠獲得id的值

2、若是是路徑傳參

    能夠經過傳參的形式,當正則表達式寫一個(\d+)的時候,就給函數傳一個id,可經過這個id知道id.
View Code

第11章 做業

做業要求,在Django裏面實現一個簡單的表單數據查詢、新增、修改、刪除等。

相關文章
相關標籤/搜索