1. 程式人生 > >框架--1、django

框架--1、django

域名 日期和時間 rom not strong 前端 還要 之間 定向

web框架

  框架,即framework,特指為解決一個開放性問題而設計的具有一定約束性的支撐結構,使用框架可以幫你快速開發特定的系統,以避免重復造輪子。

  所有的Web應用,本質上是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端。

技術分享圖片
import socket

def handle_request(client):

    buf = client.recv(1024)
    client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8"))
    client.send("<h1 style=‘color:red‘>Hello, yuan</h1>
".encode("utf8")) def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind((localhost,8001)) sock.listen(5) while True: connection, address = sock.accept() handle_request(connection) connection.close() if __name__ == __main__: main()
View Code

接受HTTP請求、解析HTTP請求、發送HTTP響應這些底層功能由專門的服務器軟件實現,通過接口WSGI:Web Server Gateway Interface完成。

MTV模式

Model(模型):負責業務對象與數據庫的對象(ORM)

Template(模版):負責如何把頁面展示給用戶

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

此外,Django還有一個url分發器,它的作用是將一個個URL的頁面請求分發給不同的view處理,view再調用相應的Model和Template

技術分享圖片

環境:

  通過“cmd”打開一個新的命令提示符窗口,直接輸入:“django-admin.py”,如果提示:“‘django- admin.py‘ 不是內部或外部命令,也不是可運行的程序或批處理文件,那先下載安裝,之後配好環境變量。

創建一個django項目

  在django已經安裝完畢、環境變量也配置好了,執行創建django項目的命令。

  通過命令:“django-admin.py startproject [projectname]”在當前目錄下建立一個名為[projectname]的項目。

  pycharm創建如下:

技術分享圖片

  註:需要確保py的打開方式是python解釋器,不是則右鍵任意py文件選擇默認的打開方式為python解釋器就好啦!

創建好的django項目長這樣:

     技術分享圖片

註:若是命令創建,則沒有templates目錄

manage.py

是與項目進行交互的命令行工具集的入口,是Django中的項目管理器,運行命令:

python manage.py 可以查看manage.py 的相關命令

與項目同名的子目錄

這個目錄是項目的一個容器,包含項目的一些基本配置,文件名理論上可以隨意修改,但並不建議這樣做。這是因為配置文件中很多配置引用到這個文件名,無需修改。

其中的文件

1.wsgi.py

wsgi(Python Web Server Gateway Interface)即Python服務器網關接口,是python應用與Web服務器之間的接口。

2.urls.py

URL配置文件。Django項目中所有地址(頁面)都需要我們去配置URL。

3.settins.py

BASE_DIR:項目的根目錄;
SECRET_KEY:安全碼;
DEBUG:調試,實際生產中需要將其值設置為* false *;
ALLOWED_HOSTS:設置允許的外界訪問的地址;
INSTALLED_APPS:記錄加載的應用;
MIDLEWEAR:自帶的工具集;
ROOT_URLCONF:URL根文件的配置文件;
TEMPLATES:模板文件,模板指的是一個個HTML文件;
WSGI_APPLICATION:
DATABASES:數據庫文件,默認是sqlite3,如果要使用其他數據庫可以到Django官網有關數據庫配置的文檔了解;
AUTH_PASSWORD_VALIDATORS:與密碼認證有關;
LANGUAGE_CODE:語言,默認是un-es即美式英語;
TIME_ZONE:時區;
STATIC_URL:靜態文件(CSS,JavaScript,images等)的地址。

4.init.py

聲明模塊,內容默認為空。

技術分享圖片
STATIC文件還可以配置STATICFILES_DIRS,指定額外的靜態文件存儲位置。
    #  STATIC_URL的含義與MEDIA_URL類似。

    # ----------------------------------------------------------------------------
    #註意1:
        #為了後端的更改不會影響前端的引入,避免造成前端大量修改

        STATIC_URL = /static/               #引用名
        STATICFILES_DIRS = (
            os.path.join(BASE_DIR,"statics")  #實際名 ,即實際文件夾的名字
        )

        #django對引用名和實際名進行映射,引用時,只能按照引用名來,不能按實際名去找
        #<script src="/statics/jquery-3.1.1.js"></script>
        #------error-----不能直接用,必須用STATIC_URL = ‘/static/‘:
        #<script src="/static/jquery-3.1.1.js"></script>

    #註意2(statics文件夾寫在不同的app下,靜態文件的調用):

        STATIC_URL = /static/

        STATICFILES_DIRS=(
            (hello,os.path.join(BASE_DIR,"app01","statics")) ,
        )

        #<script src="/static/hello/jquery-1.8.2.min.js"></script>

    #註意3:
        STATIC_URL = /static/
        {% load staticfiles %}
       # <script src={% static "jquery-1.8.2.min.js" %}></script>
settings的配置

在項目裏創建應用

  python manage.py startapp myblog

技術分享圖片

並添加應用名到settings.py中的INSTALLED_APPS中(註:應用名不可以與模塊名相同)

應用的文件結構:

  • migrations:一個數據遷移的模塊,內容自動生成
  • admin.py 該應用的後臺管理系統
  • apps.py 該應用的一些配置,Django-1.9以後自動生成
  • models.py 數據模塊,使用ORM框架
  • tests.py 自動化測試的模塊
  • views.py 執行響應的代碼所在模塊,是代碼邏輯處理的主要地點,項目中大部分代碼在這裏編寫

啟動django項目

python manage.py runserver 8888

註:此處指指定端口,若不指定IP和端口,默認為http://127.0.0.1:8000/

訪問時的默認頁面為

技術分享圖片

django重要文件介紹:

urls.py 路由配置系統(URLconf)

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

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


參數說明:
一個正則表達式字符串
一個可調用對象,通常為一個視圖函數或一個指定視圖函數路徑的字符串
可選的要傳遞給視圖函數的默認參數(字典形式)
一個可選的name參數

URLconf的正則字符串參數

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),
]
技術分享圖片
    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)。
註意

有名分組(named group)

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

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

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

技術分享圖片
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),
]
View Code

這個實現與前面的示例完全相同,只有一個細微的差別:捕獲的值作為關鍵字參數而不是位置參數傳遞給視圖函數

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

URLconf 在什麽上查找

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

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

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

URLconf 不檢查請求的方法。換句話講,所有的請求方法 —— 同一個URL的POSTGETHEAD等等 —— 都將路由到相同的函數。

捕獲的參數永遠是字符串

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

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

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

指定視圖參數的默認值

有一個方便的小技巧是指定視圖參數的默認值。 下面是一個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 值。

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

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

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

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

views.py 視圖

一個視圖函數,或者簡短來說叫做視圖,是一個簡單的Python函數,它接受web請求,並且返回web響應。響應可以是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片. . . 是任何東西都可以。無論視圖本身包含什麽邏輯,都要返回響應。代碼寫在哪裏也無所謂,只要它在你的Python目錄下面。除此之外沒有更多的要求了——可以說“沒有什麽神奇的地方”。為了能夠把代碼放在某個地方,慣例是把視圖放在叫做views.py的文件中,然後把它放到你的項目或者應用目錄裏。

一個返回當前日期和時間作為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)

逐行分解

  • 首先,我們從 django.http模塊導入了HttpResponse類,以及Python的datetime庫。
  • 接著,我們定義了current_datetime函數。它是一個視圖函數。每個視圖函數都應接收HttpRequest對象作為第一個參數,一般叫做request。
  • 註意視圖函數的名稱並不重要;不需要用一個統一的命名方式來命名,以便讓Django識別它。我們將其命名為current_datetime,是因為這個名稱能夠精確地反映出它的功能。
  • 這個視圖會返回一個HttpResponse對象,其中包含生成的響應。每個視圖函數都要返回HttpResponse對象

http請求-響應過程中有兩個核心對象:

http請求對象:HttpRequest

http響應響應:HttpResponse

所在位置:django.http

其中封裝好的函數

render函數

---------------render(request, template_name[, context])

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

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

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

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

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

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

redirect函數

----------redirect(/uri)

總結: render和redirect的區別: 1 if render的頁面需要模板語言渲染,需要的將數據庫的數據加載到html,那麽所有的這一部分 # 除了寫在yuan_back的視圖函數中,必須還要寫在login中,代碼重復,沒有解耦. 2 the most important: url沒有跳轉到/yuan_back/,而是還在/login/,所以當刷新後 # 又得重新登錄.

Template

模板系統的介紹

不要將HTML被直接硬編碼在 Python代碼之中。

  • 對頁面設計進行的任何改變都必須對 Python 代碼進行相應的修改。 站點設計的修改往往比底層 Python 代碼的修改要頻繁得多,因此如果可以在不進行 Python 代碼修改的情況下變更設計,那將會方便得多。

  • Python 代碼編寫和 HTML 設計是兩項不同的工作,大多數專業的網站開發環境都將他們分配給不同的人員(甚至不同部門)來完成。 設計者和HTML/CSS的編碼人員不應該被要求去編輯Python的代碼來完成他們的工作。

  • 程序員編寫 Python代碼和設計人員制作模板兩項工作同時進行的效率是最高的,遠勝於讓一個人等待另一個人完成對某個既包含 Python又包含 HTML 的文件的編輯工作。

基於這些原因,將頁面的設計和Python的代碼分離開會更幹凈簡潔更容易維護。 我們可以使用 Django的 模板系統 (Template System)來實現這種模式,這就是本章要具體討論的問題。

python的模板:HTML代碼+邏輯控制代碼

模板支持的語法

變量(使用雙大括號來引用變量)

語法格式:       {{var_name}}
python manange.py shell  (###進入該django項目的環境)
from django.template import Context, Template
t = Template(Hello, {{ name }})
for name in (John, Julie, Pat):
    print t.render(Context({name: name}))

Django 模板解析非常快捷。 大部分的解析工作都是在後臺通過對簡短正則表達式一次性調用來完成。 這和基於 XML 的模板引擎形成鮮明對比。

{% if %} 的使用

{% if %}標簽計算一個變量值,如果是“true”,即它存在、不為空並且不是false的boolean值,系統則會顯示{% if %}和{% endif %}間的所有內容

{% if num >= 100 and 8 %}

    {% if num > 200 %}
        <p>num大於200</p>
    {% else %}
        <p>num大於100小於200</p>
    {% endif %}

{% elif num < 100%}
    <p>num小於100</p>

{% else %}
    <p>num等於100</p>

{% endif %}



{% if %} 標簽接受and,or或者not來測試多個變量值或者否定一個給定的變量
{% if %} 標簽不允許同一標簽裏同時出現and和or,否則邏輯容易產生歧義,例如下面的標簽是不合法的:

{% if obj1 and obj2 or obj3 %} 

{% for %}的使用

{% for %}標簽允許你按順序遍歷一個序列中的各個元素,每次循環模板系統都會渲染{% for %}和{% endfor %}之間的所有內容

技術分享圖片
<ul>
{% for obj in list %}
    <li>{{ obj.name }}</li>
{% endfor %}
</ul>


#在標簽裏添加reversed來反序循環列表:

    {% for obj in list reversed %}
    ...
    {% endfor %}

#{% for %}標簽可以嵌套:

    {% for country in countries %}
        <h1>{{ country.name }}</h1>
        <ul>
         {% for city in country.city_list %}
            <li>{{ city }}</li>
         {% endfor %}
        </ul>
    {% endfor %}


#系統不支持中斷循環,系統也不支持continue語句,{% for %}標簽內置了一個forloop模板變量,
#這個變量含有一些屬性可以提供給你一些關於循環的信息

1,forloop.counter表示循環的次數,它從1開始計數,第一次循環設為1:

    {% for item in todo_list %}
        <p>{{ forloop.counter }}: {{ item }}</p>
    {% endfor %}
2,forloop.counter0 類似於forloop.counter,但它是從0開始計數,第一次循環設為0
3,forloop.revcounter
4,forloop.revcounter0
5,forloop.first當第一次循環時值為True,在特別情況下很有用:
    {% for object in objects %}   
         {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}   
         {{ object }}   
        </li>  
    {% endfor %}  
    
# 富有魔力的forloop變量只能在循環中得到,當模板解析器到達{% endfor %}時forloop就消失了
# 如果你的模板context已經包含一個叫forloop的變量,Django會用{% for %}標簽替代它
# Django會在for標簽的塊中覆蓋你定義的forloop變量的值
# 在其他非循環的地方,你的forloop變量仍然可用


#{% empty %}

{{li }}
      {%  for i in li %}
          <li>{{ forloop.counter0 }}----{{ i }}</li>
      {% empty %}
          <li>this is empty!</li>
      {% endfor %}

#         [11, 22, 33, 44, 55]
#            0----11
#            1----22
#            2----33
#            3----44
#            4----55
例子

extend模板繼承

到目前為止,我們的模板範例都只是些零星的 HTML 片段,但在實際應用中,你將用 Django 模板系統來創建整個 HTML 頁面。 這就帶來一個常見的 Web 開發問題: 在整個網站中,如何減少共用頁面區域(比如站點導航)所引起的重復和冗余代碼?Django 解決此類問題的首選方法是使用一種優雅的策略—— 模板繼承

本質上來說,模板繼承就是先構造一個基礎框架模板,而後在其子模板中對它所包含站點公用部分和定義塊進行重載。

可以對那些不同 的代碼段進行定義,而不是 共同 代碼段。

第一步是定義 基礎模板,該框架之後將由子模板所繼承。 以下是我們目前所講述範例的基礎模板:

技術分享圖片
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    {% block content %}{% endblock %}
    {% block footer %}
    <hr>
    <p>Thanks for visiting my site.</p>
    {% endblock %}
</body>
</html>
View Code

子模板的作用就是重載、添加或保留那些塊的內容。

我們使用模板標簽: {% block %} 。 所有的 {% block %} 標簽告訴模板引擎,子模板可以重載這些部分。 每個{% block %}標簽所要做的是告訴模板引擎,該模板下的這一塊內容將有可能被子模板覆蓋。

現在我們已經有了一個基本模板,我們可以修改 current_datetime.html 模板來 使用它:

{% extends "base.html" %}
 
{% block title %}The current time{% endblock %}
 
{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}

每個模板只包含對自己而言 獨一無二 的代碼。

框架--1、django