1. 程式人生 > >Django的基本使用

Django的基本使用

django template view url python

小生博客:http://xsboke.blog.51cto.com

小生 Q Q:1770058260

                            -------謝謝您的參考,如有疑問,歡迎交流

一、靜態文件
二、路由映射
三、視圖函數
四、template(模板)基礎

  1. 關於靜態文件

    1.1 首先需要在配置文件settings.py中指定靜態目錄
    STATICFILES_DIRS = (
    os.path.join(BASE_DIR,"statics"),
    )

    1.2 然後在html中使用django模板語言指定靜態文件
    {% load static from staticfiles %}

    <link href="{% static "index.css" %}" rel="stylesheet" type="text/css" />
    <script src="{% static "index.js" %} "></script>

    1.3 也可以這樣寫

    # 指定前綴
    STATIC_URL = ‘/a/‘ 
    
    STATICFILES_DIRS = (
    os.path.join(BASE_DIR,"statics"),
    )
    
    <link href="/a/css/index.css" rel="stylesheet" type="text/css" />
    <script src="/a/js/index.js"></script>
  2. 路由映射

    Django URL是一個URL和視圖函數的映射表

    urlpatterns = [
    path(‘admin/‘, admin.site.urls),
    ]

    urlpatterns = [
    url(正則表達式,views視圖函數,參數,別名)
    ]
    參數:可選的要傳遞給視圖函數的默認參數
    別名:一個可選的name參數,用於前端

    註意:要想使用url去配置路徑需要加載模塊:from django.conf.urls import url

    2.1 無名分組
    url(r‘^articles/[0-9]{4}/([0-9]{4})/([0-9]+)/$‘,views.special_case_2018),
    ^articles:以articles開頭匹配articles

    /:目錄符號
    [0-9]{4}:包含一個4位數,每一位的範圍是0-9
    ():加括號的意思是傳入一個參數
    這時候,views.py需要這樣寫(使用HttpResponsen需要導入這個模塊):
    def special_case_2018(req,變量) #可以傳入多個變量,用逗號分隔
    return HttpResposen(變量+"year") #將用戶輸入的內容返回到瀏覽器上

    2.2 命名分組

    2.2.1 講解
    import re

    ret = re.search(‘(?P<id>\d{3})/(?P<name>\w{3})‘,‘weeew34ttt123/ooo‘)
    
    ?P:固定格式,意思是這種分組是有名字的
    <id>:匹配的名字就是id,可以看做是一個變量,是匹配內容的變量
    \d{3}:是匹配的內容,3個數字。
    \w{3}:就是3個字母
    ‘weeew34ttt123/ooo‘:這段字符串就是被匹配的內容,最終結果會匹配出"123/ooo"
    
    print(ret.group())      :取出所有匹配到的內容
    print(ret.group(‘id‘))  :只取出名字為的id的內容
    print(ret.group(‘name‘)):只取出名字為的name的內容

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

    views.py配置
    def year_archive(req,year,month):               # 使用命名分組,形參必須是url中定義的名字,順序可以不同
        return HttpResposen(year+"y"+month+"m")

    2.3 參數三
    urlpatterns = [
    url(r‘index‘,views.index,{"name":‘dashan‘}),
    ]

    def index(req,name):
        return HttpResposen(name)       # 返回"dashan"
        # 如果在使用參數的同時,使用了命名分組,兩邊的名字如果一樣,那麽參數會覆蓋命名分組

    2.4 參數四
    urlpatterns = [
    url(r‘index‘,views.index,name="dashan"), # name是固定的寫法,name就是別名
    ] # name="dashang",代替的就是index,就是index的別名

    這時候,前端可以通過別名去找到視圖函數
    
    <form action={% url "dashan" %} method="post">
        <input type="text" name="usernmae">
        <input type="passwrod" name="passwd">
        <input type="submit" name="submit">
    <form>

    2.5 url映射分發(include)
    當有上萬頁面時,你就得在urls.py中寫上萬條url匹配,造成數據量大,容易寫重,容易造成結藕

    解決方法:在每個app下創建一個urls.py,全局的urls.py只做一個映射
    
    2.5.1 全局urls.py
    
        from django.conf.urls import url,include
        from appname import views
    
        urlpatterns = [
            url(r‘^appname‘,include(‘appname.urls‘)),
        ]
    
    2.5.2 app的urls.py
        from django.conf.urls import url,include
    
        urlpatterns = [
            url(r‘page1/page1.1‘,views.page1),      # page1是緊跟appname的內容
            url(r‘page2‘,views.page2),
        ]
  3. 視圖函數

    HTTP請求中產生兩個核心對象:
    http請求:HttpRequest對象
    http響應:HttpResponse對象
    所在位置:django.http

    # 獲取兩種請求方法
    request.POST.get
    request.GET.get

    3.1 HttpRequest對象的屬性
    path: 請求頁面的全路徑,不包括域名
    method: 請求中使用的HTTP方法的字符串表示,全大寫表示。例如GET和POST
    if req.method == "POST" or req.method == "GET"
    GET: 包含所有HTTP GET參數的類字典對象
    POST: 包含所有HTTP POST參數的類字典對象
    服務器收到空的POST請求的情況也是可能發生的,也就是說,表單form通過
    HTTP POST方法提交請求,但是表單中可能沒有數據,因此不能使用
    if req.POST 來判斷是否使用的HTTP POST 方法,應該使用 if req.method == "POST"

    COOKIES:    包含所有cookies的標準python字典對象;key和values都是字符串
    FILE:       包含所有上傳文件的類字典對象;files中的米一個key都是<input type="file" name="" />標簽中
                name的屬性值,files中的每一個values同時也是一個標準的python字典對象,包含下面是哪個keys:
    
                    filename:       上傳文件名,用字符串表示
                    content_type:   上傳文件的Content Type
                    content:        上傳文件的原始內容
    user:       是一個Django.contrib.auth.models.User對象,代表當前登錄的用戶,如果訪問用戶當前沒有登錄,
                user將初始化為django.contrib.auth.models.AnonymousUser的實例。你可以通過user的
                is_authenticated()方法來辨別用戶是否登錄:
                    if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware時,該屬性
                    才可用
    
    session:    唯一可讀寫的屬性,代表當前會話的字典對象;只有激活Django中的session支持時該屬性才可用

    3.2 HttpResponse對象
    對於HttpRequest對象來說,是由django自動創建的,但是,HttpResponse對象就必須我們自己創建,
    每個view請求處理方法必須返回一個HttpResponse對象。

    HttpResponse類在django.http.HttpResponse
    在HttpResponse對象上擴展的常用方法:
        頁面渲染: render(),render_to_response(),  
            # 使用render_to_response()方法需要引入render_to_response模塊
                return render(req,"index.html")
                return render_to_response("index.html")         -- 有坑不建議使用
    
        本地變量:locals():  可以直接將函數中所有的變量傳給模板,locals是本地變量的意思,將本地變量傳入html中
            例:
                views.py 中寫
                    name="dashan"
                    return render_to_response("index.html",{"a":name})  
                html就得寫
                    {{ a }}
    
                當views.py 這樣寫
                    name="dashan"
                    return render_to_response("index.html",locals())
    
                html就可以這樣寫,直接調用變量,而不需要使用參數調用
                    {{ name }}
    
                註意,使用render也可以
    
        頁面跳轉(重定向): redirect()
            return redirect("http://www.baidu.com")
            return redirect("http://www.baidu.com")
    
            render 是直接渲染某個頁面並返回,redirect是重定向到指定的views函數,同時也會做一定的判斷,
            比如用戶登錄。
  4. template基礎

    在向前端輸出字符串時使用模板語言進行處理,而不是使用 "歡迎 %s 登錄" %(name) ,這種方式是為了實現前後端分離

    什麽是模板語言?
    格式:HTML + 邏輯控制語句,如果HTML中存在模板語言,則HTML就叫模板,而不是HTML

    模板語言的作用?
    起到前端到後端的紐帶作用

    render(request,"index.html",{"name":name})
        "index.html"        就叫模板
        {"name":name}       就叫上下文,Context
    
    在pycharm的terminal界面輸入python manage.py shell即可進入當前django的命令行
    輸入:
    >>> t=Template("hello {{ name }}")          創建模板語言
    >>> c=Context({"name":"dashan"})            創建上下文
    >>> t.render(c)                             渲染模板語言和上下文
    ‘hello dashan‘

    4.1 一次模板創建,多次調用render()實現更高效的渲染

    t = Template("hello, {{ name }}")
    for name in (‘dashan‘,‘lisi‘,‘wangwu‘):
        print t.render(Context({‘name‘}:name))
    
    在view中使用Template和Context需要引入,from django.template import Template,Context

    4.2 深度變量的查找(萬能的句點號".")

    import datetime
    
    def index(req):
        s=[1,2,3,4]
        s2={"uname":"dashan","sex":23}
        s3=datetime.datetime.now()
    
        class Person:
            def __init__(self,name,age):
                self.name = name
                self.age = age
    
        s4=Person("dashan",18)
    
        return render(req,"index.html",{"list":s})
        return render(req,"index.html",{"obj":s2})
        return render(req,"index.html",{"time":s3})
        return render(req,"index.html",{"P":s4})
    
    <html>
        <p> Template </p>
        {{ list.2}}   <!-- 輸出的結果是3 ,列表通過索引取值-->
        {{ obj.sex}}   <!-- 輸出的結果是23,字典通過key取values -->
        {{ time.year }}   <!-- 屬性也是通過"."召喚出來的 -->
        {{ time.month }}   <!-- 屬性也是通過"."召喚出來的 -->
        {{ P.age }}   <!-- 屬性也是通過"."召喚出來的,結果是18 -->
        {{ P }}   <!-- 如果不加屬性,那麽輸出的是一個對象屬性 -->
    </html>

    4.3 if和for循環

    4.3.1 if,只支持布爾值True或者False,1(True)和(False)也可以
    
        { % if True % }
            <p>hello world</p>
            { % elif obj % }
                <p>hello2</p>
        { % endif % }
    
    4.3.2 for
        # 用列表舉例
        { % for i in list % }
            <p>{{ i }}</p>          <!--  i 是vaules,和js不一樣(js取的是索引) -->
            <p>{{ forloop.counter }}:{{ i }}</p>        <!--  輸出"索引值:values",索引從1開始 -->
            <p>{{ forloop.counter0 }}:{{ i }}</p>       <!--  輸出"索引值:values",索引從0開始 -->
            <p>{{ forloop.revcounter }}:{{ i }}</p>     <!--  輸出"索引值:values",索引反著打印 -->
        { % endfor % }
    
        # 用字典舉例
        { % for i in obj % }    
            <p>{{ forloop.counter }}:{{ i }}</p>        <!--  輸出"索引值:key",索引從1開始,和列表一樣 -->
            <p>{{ forloop.counter }}:{{ i.uname }}</p>      <!--  輸出"索引值:values",這樣就可以打印值了 -->
        { % endfor % }
    
        # 字典的使用方法
        {% for row in user_dict.keys %}
        {% for row in user_dict.values %}
    
        {% for row in user_dict.items %} 得到元組
    
        {% for k,row in user_dict.items %}

       <li>{{k}}-{{row}}</li>
    {% endfor %}

    4.4 過濾器filter
    {{ ship_date|date:"Fj,Y"}}
    ship_date變量傳給date過濾器,date過濾器通過使用"Fj,Y"這幾個參數來格式化日期數據,
    "|"和unix的管道符類似

    s = "hello"
    s2 = 1
    s3 = datetime.datetime.now()
    s4 = []
    s5 = "<a href="http://www.baidu.com">百度</a>"
    return render(req,"index.html",{"obj":s})
    return render(req,"index.html",{"num":s2})
    return render(req,"index.html",{"time":s3})
    return render(req,"index.html",{"kong":s4})
    return render(req,"index.html",{"a":s5})
    
    <html>
        {{ 對象|方法:參數}}       - 格式
    
        {{ obj }}               - 打印結果"hello".
        {{ obj|upper }}         - 使用模板語言中的upper方法,將"hello"轉為大寫"HELLO".
        {{ obj|lower }}         - 小寫
        {{ obj|firest }}        - 取出第一個字母
        {{ obj|capfirest }}     - 將第一個字母大寫
    
        {{ num|add:5 }}         - num+5 ,結果為6
    
        {{ 對象|cut: ‘ ‘}}        - 去除空格
        {{ time|date: ‘Y-m-d‘}}     - 輸出年月日,"-"也可以寫為":"
    
        {{ kong|default: ‘空的‘}} - 當對象為空時,輸出default指定的字符串,如果不為空則輸出對象
    
        {{ % a % }}             - 會將超鏈接返回為一個字符串,因為瀏覽器會認為是不安全的
    
        { % autoescape off % }  - 這樣瀏覽器就能解析為html語言了,瀏覽器就認為是安全的
            {{ % a % }} 
        { % endautoescape % }
    
        {{ a|safe }}            - 這個和上面那個是一樣的功能,會告訴瀏覽器這是安全的
    
        {{ obj|filesizeformat }} -  打印對象的大小
        {{ obj|length }}         -  打印對象的長度
        {{ obj|slice: ‘:-1‘ }}   -  切片,從頭切到最後一個,最後一個不要
        {{ a|urlencode }}
    
        values="hello I am shan"
        {{ values|truncatechars:‘6‘ }}      按字符截取
        {{ values|truncatewords:‘2‘ }}      按單詞截取
    
    </html>
    
    註意:為什麽要在前端轉而不是後端,試想一下如果輸入的是一個字典類型的數據,需要
        for循環完後的數據輸出為大寫,如果你在後端做這個操作的話就會變得很繁瑣,需要
        循環完後賦予一個變量才能轉給前端

    4.5 中間件 csrf 跨站請求偽造

    用於生成csrf_token的標簽,用於防治跨站攻擊驗證。
    
    用於驗證form表單
    <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>
        {% csrf_token %}        <!-- 指定認證,否則報錯Forbidden
                                 django會渲染出一個令牌(input標簽),
                                 擁有類型hidden,名字和值,用於告訴Django,
                                 我是一個認證過的表單
                                  -->
    </form>
    
    註意:
        同時如果你在views.py中返回頁面時使用 render_to_response,需要這樣寫
    
        from django.template import RequestContext,Template
    
        return render_to_response("index.html",context_instent=RequestContext(request))
    
        否則也會報錯Forbidden,所以之前才不建議使用render_to_response

    4.6 { % load % } - 加載標簽庫

    4.7 { % url % } - 引用路由配置的地址

    4.8 { % with % } - 用更簡單的變量名替代復雜的變量名

    { % with total=fadsfsadfdsaffdsaf % } {{ total }} { % endwith % }
    
    格式:{ % with 新變量名=舊變量名 % } {{ 新變量名 }} { % endwith % }

    4.9 { % varbatim % } - 禁止render

    { % varbatim % }            - name就不會渲染了,輸出的就是字符串"{{ name }}    "
        {{ name }}      
    { % endvarbatim % }

    4.10 自定義 simple_tag

    需求:比如後端傳給了前端一個變量num=1,我想讓這個變量在前端+10,
        原本我可以在前端寫為 {{ num|add:‘10‘}},但是我想使用自定義的方法
        {{ num|add100 }},這就叫做自定義simple_tag(簡單標簽)
    
    a. 在app目錄下中創建templatetags模塊
    b. 創建任意.py文件,如文件名"my_tag.py"
        #!/usr/bin/evn python
        #coding:utf-8
        from django import template
        from django.utils.safestring import mark_safe
    
        register = template.Library()   # register是固定變量名,不能改變
    
        @register.simple_tag            # 裝飾器
        def my_add100(v1):
            return v1 + 10              # 實現num+10
    
        @register.simple_tag
        def my_input(id,arg):
            result = "<input type="text" id="%s" class="%s">" %(id.arg)
            return mark_safe(result)
    
    c. 在使用自定義simple_tag的html文件中引入之前創建的mytag.py文件名
    
        { % load my_tag % }
    
        <html>
        </html>
    
    d. 使用simple_tag
        <html>
            { % my_add100 1 % }    <!-- 輸出11 -->
        </html>
    
        <html>
            { % my_input id1 cl1 % }    <!-- 輸出一個input標簽,id是id1,class是cl1 -->
        </html>

    4.11 自定義filter
    流程和自定義 simple_tag一樣,就差在
    @register.simple_tag了,自定義filter是這樣寫@register.filter

        調用方式為
        {{ num|my_add100 }}         <!-- 輸出11 相當於執行"my_add100(num)" -->
    
        如果自定義filter傳入的是兩個參數,最多也只能兩個(自定義 simple_tag沒有這個限制),
        解決方法是傳入一個列表
    
        @register.filter                # 裝飾器
        def my_add100(v1,v2):
            return v1 + 10 + v2     
    
        {{ num|my_add100:2 }}       <!-- 輸出13 -->   
    
        註意:模板的if語句可以加一個自定義filter,但是不能加自定義simple_tag
                同時,使用自定義簡單標簽和自定義filter,必須在全局文件settings.py中的
                INSTALLED_APPS [
                        ‘myapp‘,
                ]
                區域添加你的app名

Django的基本使用