9、Django的鎖、事務、ajax

1、事務和鎖html

  1. 行級鎖

select_for_update 注意必須用在事務裏面mysql

select_for_update(nowait=False, skip_locked=False)jquery

entries = Entry.objects.select_for_update().filter(author=request.user)  #加互斥鎖,因爲mysql在查詢時自動加的是共享鎖,因此咱們能夠手動加上互斥鎖。create、update、delete操做時,mysql自動加行級互斥鎖

select * from t1 where id=1 for update;
models.T1.objects.select_for_update().fitler(id=1)

全部匹配的行將被鎖定,直到事務結束。這意味着能夠經過鎖防止數據被其它事務修改。ajax

  1. 事務

第一種方式:全局的sql

這種方式是統一個http請求對應的全部sql都放在一個事務中執行(要麼全部都成功,要麼全部都失敗),是全局性的配置數據庫

在settings文件中:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mxshop',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': '123',
        'OPTIONS': {
            "init_command": "SET default_storage_engine='INNODB'",
       #'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", #配置開啓嚴格sql模式


        }
        "ATOMIC_REQUESTS": True, #全局開啓事務,綁定的是http請求響應整個過程
        "AUTOCOMMIT":False, #全局取消自動提交,慎用
    },
  'other':{
    'ENGINE': 'django.db.backends.mysql', 
            ......
  } #還能夠配置其餘數據庫
}

第二種方式:局部的django

經過transaction中的atomic代碼塊實現瀏覽器

from django.db import transaction  # 導入transaction

在視圖函數中加:
@transaction.non_atomic_requests
def index(request):
    pass (orm...sql..語句)
    return xxx

上下文邏輯裏面加:
def index(request):
    ..
    with transaction.atomic():  # 設置事務的保存點
        pass orm...sql..
    ...
    return xxx

2、Ajax服務器

  1. 簡介app

    AJAX (Asynchronous Javascript And XML) ,翻譯成中文是「異步的Javascript和XML」 ,即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML 。

    AJAX 最大的優勢是在不從新加載整個頁面的狀況下,能夠與服務器交換數據並更新部分網頁內容。(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程)

    AJAX 不須要任何瀏覽器插件,但須要用戶容許JavaScript在瀏覽器上執行

AJAX除了異步的特色外,還有一個就是:瀏覽器頁面局部刷新;

  • 異步交互:客戶端發出一個請求後,無需等待服務器響應結束,就能夠發出第二個請求
  • 局部刷新:這一特色給用戶的感覺是在不知不覺中完成請求和響應過程
  1. 普通的登陸認證示例

首先不用ajax,完成一個登陸認證的界面

  1. 配置路由 urls
    from app01 import views
    urlpatterns = [
    url(r'^login/', views.LoginView.as_view(),name='login'),
    # 這是CBV開始時配置的路徑
    ]

  2. CBV的方式完成視圖函數
    from django.shortcuts import render,HttpResponse,redirect
    from django.views import View

    class LoginView(View):
        def get(self,request):
            return render(request,'login.html')
    
        def post(self,request):
            name = request.POST.get('username')
            pwd = request.POST.get('password')
            if name=='yangzm' and pwd=='123':
                return render(request,'index.html')
            else:
                return redirect('login')
  3. 完成兩個html文件,login.html用來完成登陸功能;index.html文件完成登陸成功後顯示的頁面,若是用戶名密碼錯誤,重定向會login.html的頁面
    # login.html

    歡迎來到登陸頁面



    {% csrf_token %}
    用戶名:
    密 碼:

    # index.html
    <p>登陸成功</p>
    <p>歡迎大佬到來</p>
  4. 結果和分析缺點
    用戶輸入127.0.0.1:8000/login/時,顯示登陸頁面
    登陸成功跳轉index頁面,登陸失敗從新返回這個頁面

    分析缺點:當用戶輸入信息不正確的時候,由於作了重定向,點擊提交後,頁面刷新,跳轉回了login頁面,此時是又從新請求的頁面,因此之前輸入的數據將會被清空,這樣對用戶來講,體驗是極差的
    改進的目標:用戶輸入錯誤時,要保留以前的信息,並提示用戶輸入錯了,而後讓用戶在輸入的內容上改,提升用戶的體驗,這時,就須要用到ajax來完成這個功能

  5. 基於ajax完成的登陸認證示例

  6. ajax須要用到jquery的文件,因此先配置靜態文件引入
    # 配置settings:
    STATICFILES_DIRS=[
    os.path.join(BASE_DIR,'statics')
    ]

    # 新建文件夾statics,放靜態文件 jquery.js
  7. 此時login.html文件須要引入jquery文件,而後寫js代碼,實現ajax
    {% load static %}

    <body>
    <h1>歡迎來到登陸頁面</h1>
    
    <form action="/login/" method="post">
        {% csrf_token %}
        用戶名:<input type="text" id="username" name="username">
        密  碼:<input type="password" id="password" name="password">
        <input type="button" id="btn" value="提交">
        <span style="color: red;font-size: 12px" id="error"></span>
    </form>
    
    
    <script src="{% static 'jquery.js' %}"></script>
    <script>
        $('#btn').click(function () {
            $.ajax({
                url:'/login/',
                type:'post',
                data:{
                    uname:$('#username').val(),
                    pwd:$('#password').val(),
                    csrfmiddlewaretoken:$('[name=csrfmiddlewaretoken]').val()
                    # 這是爲了經過post提交的認證機制
    
                },
                success:function (res) {
                    var resStr = JSON.parse(res);
                    if(resStr['code'] === 3){
                        $('#error').text(resStr['redirect_url'])
                    }
                    else if(resStr['code'] === 0){
                        location.href=resStr['redirect_url'];
                    }
                }
            })
        })
    </script>
    
    </body>
  8. url須要從新配置一個登陸成功的index路徑
    urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.LoginView.as_view(),name='login'),
    url(r'^index/', views.index),
    ]

  9. 視圖函數views
    from django.shortcuts import render,HttpResponse,redirect

    # Create your views here.
    
    from django.views import View
    
    class LoginView(View):
        def get(self,request):
            return render(request,'login.html')
    
        def post(self,request):
            name = request.POST.get('uname')
            pwd = request.POST.get('pwd')
            if name=='yangzm' and pwd=='123':
                ret = '{"code":0,"redirect_url":"/index/"}'
                return HttpResponse(ret)
            else:
                ret = '{"code":3,"redirect_url":"用戶名密碼錯誤!!!"}'
                return HttpResponse(ret)
    
    def index(request):
    
        return render(request,'index.html')
  10. 結果

    此時輸入了錯誤的用戶名密碼,不會刷新頁面,顯示提示的信息,保留原來的數據,直到輸入對了跳轉到登陸成功的頁面
  11. 外部文件導入的方式來寫js代碼,那麼js代碼中不能寫django的模板語法,由於html文件的加載順序:url--視圖--html模板渲染 --- return給瀏覽器 -- 瀏覽器渲染 --- srcipt的src --纔去請求js文件 --那麼這個js文件的代碼此時才加載到你的html文件中 -- 就沒有模板渲染的步驟了 -- 就沒有辦法替換對應的模板語法.

相關文章
相關標籤/搜索