Python學習筆記第二十五週(Django補充)

 

  一、render_to_reponse()javascript

    不一樣於render,render_to_response()不用包含request,直接寫template中文件html

  二、locals()前端

    若是views文件中的函數裏變量過多的話,能夠在render或render_to_response()裏面直接增長render(request,'index.html',locals())這樣在前端界面渲染的時候能夠直接寫變量名java

    locals()的缺點是不想傳遞過去的變量也傳遞過去了python

  三、JS中的方法:ajax

    a: hover(f1,f2)sql

      例子:數據庫

      $(".outer").hover(f1,f2) 其中f1表示鼠標進入時操做,f2表示鼠標退出時操做django

      hover比mouseover()和mouseout()的優勢在於hover一個方法能夠表示兩個動做瀏覽器

      $(".outer").hover(function(){

        clearInterval(time);

        },function(){

        time=setInterval(move,1500)#每一點五秒執行setInterval動做

         })

    b:關於輪播圖亂序問題解決:

    $('.num .li').eq(i).stop().fadeIn(1000).siblings().stop().fadeOut(1000);#加入stop表示先將播放所有中止而後在作fadeIn和fadeOut操做

   四、template中,若是要簡單標註索引可使用

    {{  forloop.counter}}  從1開始

    {{ forloop.counter0}} 從0開始

    {{forloop.revcounter}} 從最大開始

    {{ forloop.revcounter0}}從最大開始到0結束

            模板語言中,引用base模板中內容,使用{{ block.super }}

  五、ORM操做

  增長:

    #create方式一:Author.objects.create(name="Alvin")   

    #create方式二:Author.objects.create(**{"name":"Alvin"})  推薦使用

    若是有外鍵:

      一對多:

      <1>models.Book.objects.create(title="python",price=2,publish_id=2)  #其中publish爲外鍵關聯,默認使用id,因此publish_id自動生成

      <2>models.Book.objects.create(title="python",price=2,publish=obj)#publish綁定的是一對多裏面一的那個對象,也就是publish對應的   推薦

                                      #obj表明一個object對象

                  

      多對多:

      一、自動建立

        add()   remove()

      -----------正向綁定

       book=models.Book.objects.filter(id=2)[0]

      authors=models.Author.objects.filter(id__gt=2)    

      book.author.add(*authors)

      ------------反向綁定

      authors=models.Author.objects.filter(id=2)[0]

      books=models.Book.objects.filter(id__gt=2)     

      author.book_set.add(*books)                  #book_set組合在一塊兒組成一個QuerySet ,這個是django自帶的功能

    #save方式一:author=Author(name="alvin")

            author.save()

    #save方式二:authorAuthor()

          author.name="alvin"

          author.save()

    二、手動建立

       class BOOKAuthor(models.Model):

        author=models.ForeignKey('Author')

        book=models.ForeignKey('Book')

        class Meta: 

          unique_together=['author','book']  #聯合惟一

    本身寫第三張表

    ManytoMany 經過兩個ForeignKey完成

    OnetoOne     經過一個ForeignKey,uiqueTrue來完成

    

  刪除:

    models.Book.objects.filter(id=1).delete()

  改:

    第一種:author=Author.objects.get(id-5)

        authort.name='tenglan'

        author.save()

    第二種:Publisher.objects.filter(id=5).update(name='Ameriacan publshler‘)#不能用get(id=2)來查找鎖定

 

  查詢API:

    filter(**kwargs):   它包含了全部刷選條件匹配的對象

    all():          查詢全部結果

    get(**kwargs):            返回與所篩選條件匹配對象,返回結果有且只有一個,若是一個都沒匹配到會報錯

    ---------------------------------

    下面方法都是對查詢結果再進行處理,日不objects.filter().values()

    vaules(*filed)       返回一個valuequeryset-一個特殊的queryset,運行後獲得的並非一系列model實例對象,而是一個可迭代的字典序列

    exclude(**kwargs)    包含了與所給刷選條件不匹配的對象

    order_by(*filed)     對查詢結果排序,若是按照從大到小排序,可使用order_by("-id") 這種方式來進行

    reverse()      對結果反向排序

    distinct()         從返回結果中剔除重複記錄

    values_list(*filed)   它與values()很是相似,返回的是一個元組序列,values返回的是字典序列

     count()          返回數據庫中匹配查詢QuerySet的對象數量

       first()          返回第一條記錄

    last()                      返回最後一條記錄

     exists()      若是queryset包含數據,返回True,不然返回Flase

 

  

    惰性機制:

    所謂惰性機制,Pbulisher.objects.all()或者.filter()等都只是返回一個QuerySet(查詢結果集對象),它並不會立刻執行sql,而是當調用QuerySet的時候才執行。

    QuerySet特色:

    一、可迭代

    二、可切片

    #objs=models.Book.objects.all()#(obj1,obj2,obj3,.)

    #QuerySet 可迭代

    for obj in objs:每個obj就是一個行對象

      print("obj:",obj)

    #QuerySet 可切片

    #print(objs[1])

    #print(objs[1:4])

    #print(objs[::-1])

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

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

LOGGING
View Code

 

    下劃線使用:

    1、單表查詢

    models.Book.objects.filter(id__gt=2)

    models.Book.objects.filter(id__lt=2)

    models.Book.objects.filter(id__in=[1,3,4,7]) 包含,用__in

    models.Book.objects.filter(title__contian="P") #contain表示包含,icontain表示不區分大小寫

    models.Book.objects.filter(title__startwith="P")

    models.Book.objects.filter(title__endwith="P")  

    2、關聯表查詢

    models.Publish.objects.filter(book__title="pytohn",book_id=5).values("name").distinct()  #多個條件

    models.Book.objects.filter(id__gt=2,id__lt=5)       

    models.Book.objects.filter(publish__name="清華出版社").values("title")

    models.Book.objects.filter(title="python").values(「publisher__name」)

     3、聚合和分組查詢

    aggregate(*args,**kwargs):

    經過QuerySet進行計算,返回一個聚合值的字典,aggregate()中每個參數都指定一個包含在字典中的返回值,即在查詢集上生成聚合

    

from django.db.models import Avg,Min,Sum,Max

從整個查詢集生成統計值。好比,你想要計算全部在售書的平均價錢。Django的查詢語法提供了一種方式描述全部
圖書的集合。

>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}

aggregate()子句的參數描述了咱們想要計算的聚合值,在這個例子中,是Book模型中price字段的平均值

aggregate()是QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值的
標識符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。若是你想要爲聚合值指定
一個名稱,能夠向聚合子句提供它:
>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}


若是你也想知道全部圖書價格的最大值和最小值,能夠這樣查詢:
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
View Code

    

    annotate(*args,**kwargs):

       能夠經過計算查詢結果中每個對象所關聯的對象集合,從而得出總計值(也能夠是平均值或總和),即爲查詢集的每一項生成聚合。

           查詢alex出的書總價格 :

      Book.objects.filter(author__name="alex").values('title')

      Book.objects.filter(author__name="alex").aggregate(Sum('price'))

 

    查詢各個做者出的書的總價格,這裏就涉及到分組了,分組條件是author__name

      Book.objects.values("author__name").annotate(Sum('price'))

    查詢各個出版社最便宜的書價是多少

      Book.objects.values('publisher__name').annotate(MIn('price'))

 

    F查詢和Q查詢

    僅僅靠單一的關鍵字參數查詢已經很難知足查詢要求。此時Django爲咱們提供了F和Q查詢:

      

# F 使用查詢條件的值,專門取對象中某列值的操做

    # from django.db.models import F
    # models.Tb1.objects.update(num=F('num')+1)


# Q 構建搜索條件
    from django.db.models import Q

    #1 Q對象(django.db.models.Q)能夠對關鍵字參數進行封裝,從而更好地應用多個查詢
    q1=models.Book.objects.filter(Q(title__startswith='P')).all()
    print(q1)#[<Book: Python>, <Book: Perl>]

    # 二、能夠組合使用&,|操做符,當一個操做符是用於兩個Q的對象,它產生一個新的Q對象。
    Q(title__startswith='P') | Q(title__startswith='J')

    # 三、Q對象能夠用~操做符放在前面表示否認,也可容許否認與不否認形式的組合
    Q(title__startswith='P') | ~Q(pub_date__year=2005)

    # 四、應用範圍:

    # Each lookup function that takes keyword-arguments (e.g. filter(),
    #  exclude(), get()) can also be passed one or more Q objects as
    # positional (not-named) arguments. If you provide multiple Q object
    # arguments to a lookup function, the arguments will be 「AND」ed
    # together. For example:

    Book.objects.get(
        Q(title__startswith='P'),
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
    )

    #sql:
    # SELECT * from polls WHERE question LIKE 'P%'
    #     AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

    # import datetime
    # e=datetime.date(2005,5,6)  #2005-05-06

    # 五、Q對象能夠與關鍵字參數查詢一塊兒使用,不過必定要把Q對象放在關鍵字參數查詢的前面。
    # 正確:
    Book.objects.get(
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
        title__startswith='P')
    # 錯誤:
    Book.objects.get(
        question__startswith='P',
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
View Code

 

    

  六、Ajax  

  AJAXAsynchronous Javascript And XML)翻譯成中文就是異步JavascriptXML」。即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML)。

  • 同步交互:客戶端發出一個請求後,須要等待服務器響應結束後,才能發出第二個請求;
  • 異步交互:客戶端發出一個請求後,無需等待服務器響應結束,就能夠發出第二個請求。

  AJAX除了異步的特色外,還有一個就是:瀏覽器頁面局部刷新;(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程)

  

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

<script type="text/javascript">
window.onload = function() {//當文檔加載完畢時執行本函數
    var form = document.getElementById("form1");//獲取表單元素對象
    form.onsubmit = function() {//給表單元素添加一個監聽,監聽表單被提交事件
        var usernameValue = form.username.value;//獲取表單中名爲username的表單元素值
        if(!usernameValue) {//判斷該值是否爲空
            var usernameSpan = document.getElementById("usernameSpan");//獲得usernmae元素後的<span>元素
            usernameSpan.innerText = "用戶名不能爲空!";//設置span元素內容!
            return false;//返回false,表示攔截了表單提交動做
        }
        return true;//不攔截表單提交動做
    };
};
</script>
</head>
 <body>
<h1>註冊頁面</h1>
<form action="" method="post" id="form1">
用戶名:<input type="text" name="username"/>
<span id="usernameSpan"></span>
<br/>
密 碼:<input type="password" name="password"/>
<span id="passwordSpan"></span>
<br/>
<input type="submit" value="註冊"/>

</form>
  </body>
</html>

js實現的局部刷新
View Code

  Ajax常見應用場景

  

當咱們在百度中輸入一個「老字後,會立刻出現一個下拉列表!列表中顯示的是包含字的4個關鍵字。

其實這裏就使用了AJAX技術!當文件框發生了輸入變化時,瀏覽器會使用AJAX技術向服務器發送一個請求,查詢包含字的前10個關鍵字,而後服務器會把查詢到的結果響應給瀏覽器,最後瀏覽器把這4個關鍵字顯示在下拉列表中。

  • 整個過程當中頁面沒有刷新,只是刷新頁面中的局部位置而已!
  • 當請求發出後,瀏覽器還能夠進行其餘操做,無需等待服務器的響應!

  當輸入用戶名後,把光標移動到其餘表單項上時,瀏覽器會使用AJAX技術向服務器發出請求,服務器會查詢名爲zhangSan的用戶是否存在,最終服務器返回true表示名爲lemontree7777777的用戶已經存在了,瀏覽器在獲得結果後顯示用戶名已被註冊!

  • 整個過程當中頁面沒有刷新,只是局部刷新了;
  • 在請求發出後,瀏覽器不用等待服務器響應結果就能夠進行其餘操做;

    

  Ajax優缺點

  

優勢:

  • AJAX使用Javascript技術向服務器發送異步請求;
  • AJAX無須刷新整個頁面;
  • 由於服務器響應內容再也不是整個頁面,而是頁面中的局部,因此AJAX性能高;

缺點:

  • AJAX並不適合全部場景,不少時候仍是要使用同步交互;
  • AJAX雖然提升了用戶體驗,但無形中向服務器發送的請求次數增多了,致使服務器壓力增大;
  • 由於AJAX是在瀏覽器中使用Javascript技術完成的,因此還須要處理瀏覽器兼容性問題;

 

   Ajax技術:

四步操做:

  • 建立核心對象;
  • 使用核心對象打開與服務器的鏈接;
  • 發送請求
  • 註冊監聽,監聽服務器響應。

XMLHTTPRequest

  • open(請求方式, URL, 是否異步)
  • send(請求體)
  • onreadystatechange,指定監聽函數,它會在xmlHttp對象的狀態發生變化時被調用
  • readyState,當前xmlHttp對象的狀態,其中4狀態表示服務器響應結束
  • status:服務器響應的狀態碼,只有服務器響應結束時纔有這個東東,200表示響應成功;
  • responseText:獲取服務器的響應體

 

  Ajax實現

   準備工做(後臺設定):

def login(request):
    print('hello ajax')
    return render(request,'index.html')
 
def ajax_get(request):
    return HttpResponse('helloyuanhao')
View Code

  

AJAX核心(XMLHttpRequest

  其實AJAX就是在Javascript中多添加了一個對象:XMLHttpRequest對象。全部的異步交互都是使用XMLHttpServlet對象完成的。也就是說,咱們只須要學習一個Javascript的新對象便可。

var xmlHttp = new XMLHttpRequest();(大多數瀏覽器都支持DOM2規範)

注意,各個瀏覽器對XMLHttpRequest的支持也是不一樣的!爲了處理瀏覽器兼容問題,給出下面方法來建立XMLHttpRequest對象:

function createXMLHttpRequest() {
        var xmlHttp;
        // 適用於大多數瀏覽器,以及IE7和IE更高版本
        try{
            xmlHttp = new XMLHttpRequest();
        } catch (e) {
            // 適用於IE6
            try {
                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                // 適用於IE5.5,以及IE更早版本
                try{
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e){}
            }
        }            
        return xmlHttp;
    }
View Code

打開與服務器的鏈接(open方法)

當獲得XMLHttpRequest對象後,就能夠調用該對象的open()方法打開與服務器的鏈接了。open()方法的參數以下:

open(method, url, async)

  • method:請求方式,一般爲GETPOST
  • url:請求的服務器地址,例如:/ajaxdemo1/AServlet,若爲GET請求,還能夠在URL後追加參數;
  • async:這個參數能夠不給,默認值爲true,表示異步請求;
var xmlHttp = createXMLHttpRequest();
xmlHttp.open("GET", "/ajax_get/", true); 
View Code

 

  

  發送請求

  

當使用open打開鏈接後,就能夠調用XMLHttpRequest對象的send()方法發送請求了。send()方法的參數爲POST請求參數,即對應HTTP協議的請求體內容,如果GET請求,須要在URL後鏈接參數。

注意:若沒有參數,須要給出null爲參數!若不給出null爲參數,可能會致使FireFox瀏覽器不能正常發送請求!

xmlHttp.send(null);

  

  接收服務器響應

  

當請求發送出去後,服務器端Servlet就開始執行了,但服務器端的響應尚未接收到。接下來咱們來接收服務器的響應。

XMLHttpRequest對象有一個onreadystatechange事件,它會在XMLHttpRequest對象的狀態發生變化時被調用。下面介紹一下XMLHttpRequest對象的5種狀態:

  • 0:初始化未完成狀態,只是建立了XMLHttpRequest對象,還未調用open()方法;
  • 1:請求已開始,open()方法已調用,但還沒調用send()方法;
  • 2:請求發送完成狀態,send()方法已調用;
  • 3:開始讀取服務器響應;
  • 4:讀取服務器響應結束。 

onreadystatechange事件會在狀態爲1234時引起。

  下面代碼會被執行四次!對應XMLHttpRequest的四種狀態!

xmlHttp.onreadystatechange = function() {
            alert('hello');
        };

  但一般咱們只關心最後一種狀態,即讀取服務器響應結束時,客戶端纔會作出改變。咱們能夠經過XMLHttpRequest對象的readyState屬性來獲得XMLHttpRequest對象的狀態。

  

xmlHttp.onreadystatechange = function() {
            if(xmlHttp.readyState == 4) {
                alert('hello');    
            }
        };

  

  其實咱們還要關心服務器響應的狀態碼是否爲200,其服務器響應爲404,或500,那麼就表示請求失敗了。咱們能夠經過XMLHttpRequest對象的status屬性獲得服務器的狀態碼。

  最後,咱們還須要獲取到服務器響應的內容,能夠經過XMLHttpRequest對象的responseText獲得服務器響應內容。

xmlHttp.onreadystatechange = function() {
            if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                alert(xmlHttp.responseText);    
            }
        };
View Code
相關文章
相關標籤/搜索