Django框架10 /sweetalert插件、中間件、多表圖書系統總結

Django框架10 /sweetalert插件、中間件、多表圖書系統總結

1.SweetAlert插件示例

1.https://github.com/lipis/bootstrap-sweetalert
  在github下載css、js文件放到項目靜態文件夾中
2.在html頁面分別引入jquery、bootstrap文件,sweetalert是基於bootstrap實現
3.將代碼複製到script標籤中

SweetAlert代碼

$(".btn-danger").on("click", function () {
  swal({
    title: "你肯定要刪除嗎?",
    text: "刪除可就找不回來了哦!",
    type: "warning",
    showCancelButton: true,
    confirmButtonClass: "btn-danger",
    confirmButtonText: "刪除",
    cancelButtonText: "取消",
    closeOnConfirm: false
    },
    function () {
      var deleteId = $(this).parent().parent().attr("data_id");
      // 注意:此處$(this)已經不是".btn-danger"這個點擊的對象
      $.ajax({
        url: "/delete_book/",
        type: "post",
        data: {"id": deleteId},
        success: function (data) {
          if (data.status === 1) {
            swal("刪除成功!", "你能夠準備跑路了!", "success");
          } else {
            swal("刪除失敗", "你能夠再嘗試一下!", "error")
          }
        }
      })
    });
})

img

2.事務和鎖

2.1 mysql

鎖:
    select * from book where id=1 for update;
事務:
    begin
        select * from book where id=1 for update;
    commit

2.2 django orm

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

事務

1.全局開啓事務html

1.在Web應用中,經常使用的事務處理方式是將每一個請求都包裹在一個事務中。這個功能使用起來很是簡單,你只須要將它的配置項ATOMIC_REQUESTS設置爲True。

2.當有請求過來時,Django會在調用視圖方法前開啓一個事務。若是請求卻正確處理並正確返回告終果,Django就會提交該事務。不然,Django會回滾該事務。
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', 
            ......
  } #還能夠配置其餘數據庫
}

2.局部使用事務前端

用法1:給函數作裝飾器來使用python

from django.db import transaction

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()

用法2:做爲上下文管理來使用,其實就是設置事務的保存點mysql

from django.db import transaction

def viewfunc(request):
    # This code executes in autocommit mode (Django's default).
    do_stuff()

    with transaction.atomic():   #保存點
        # This code executes inside a transaction.
        do_more_stuff()

    do_other_stuff()

3. 中間件

3.1 中間件介紹

中間件顧名思義,是介於request與response處理之間的一道處理過程,相對比較輕量級,而且在全局上改變django的輸入與輸出。由於改變的是全局,因此須要謹慎實用,用很差會影響到性能。

django默認自帶的一些中間件:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

#MIDDLEWARE配置項是一個列表,列表中是一個個字符串,這些字符串實際上是一個個類,也就是一個個中間件。

3.2 自定義中間件

中間件能夠定義五個方法,分別是:(主要的是process_request和process_response)

process_request(self,request)
process_view(self, request, view_func, view_args, view_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)
以上方法的返回值能夠是None或一個HttpResponse對象,若是是None,則繼續按照django定義的規則向後繼續執行,若是是HttpResponse對象,則直接將該對象返回給用戶。

# 注意:注意將自定義中間件添加到setting文件中注意順序

process_request

process_request有一個參數,就是request,這個request和視圖函數中的request是同樣的。

# process_request方法裏面不寫返回值,默認也是返回None,若是你本身寫了return None,也是同樣的效果,不會中斷你的請求,可是若是你return 的一個httpresponse對象,那麼就會在這個方法中斷你的請求,直接返回給用戶,這就成了非正常的流程了
# 而且,若是你在這裏return了httpresponse對象,那麼會從你這個中間件類中的process_response方法開始執行返回操做,因此這個類裏面只要有process_response方法,確定會執行
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
    def process_request(self, request):
        print("MD1裏面的 process_request")

class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2裏面的 process_request")
        pass
# settings.py的MIDDLEWARE配置項
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'middlewares.MD1',  # 自定義中間件MD1,這個寫的是你項目路徑下的一個路徑,
    # 例如,若是你放在項目下,文件夾名成爲utils,那麼這裏應該寫utils.middlewares.MD1
    'middlewares.MD2'  # 自定義中間件MD2
]
MD1裏面的 process_request
MD2裏面的 process_request
app01 中的 index視圖

process_response

1.它有兩個參數,一個是request,一個是response,request就是上述例子中同樣的對象,response是視圖函數返回的HttpResponse對象。該方法的返回值也必須是HttpResponse對象
2.注意:process_response函數要有return response返回值
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class Md1(MiddlewareMixin):
    def process_request(self,request):
        print("Md1請求")
 
    def process_response(self,request,response):
        print("Md1返回")
        return response

class Md2(MiddlewareMixin):
    def process_request(self,request):
        print("Md2請求")
        #return HttpResponse("Md2中斷")
    def process_response(self,request,response):
        print("Md2返回")
        return response  ****
Md1請求
Md2請求
view函數...
Md2返回
Md1返回

cookie認證/中間件版

class M1(MiddlewareMixin):
    def process_request(self,request):
        #設置路徑白名單,只要訪問的是login登錄路徑,就不作這個cookie認證
        if request.path not in [reverse('login'),]:
            print('我是M1中間件') 
            is_login = request.COOKIES.get('is_login', False)
            if is_login:
                pass
            else:
                # return render(request,'login.html')
                return redirect(reverse('login'))
        else:
            return None #別忘了return None,或者直接寫個pass

    def process_response(self,request,response):
        print('M1響應部分')
        return response

process_view

process_view(self, request, view_func, view_args, view_kwargs)
在執行完url控制器後執行

四個參數:
request是HttpRequest對象。
1.view_func是Django即將使用的視圖函數/它是實際的函數對象,而不是函數的名稱做爲字符串。
2.view_args是將傳遞給視圖的位置參數的列表.
3.view_kwargs是將傳遞給視圖的關鍵字參數的字典/view_args和view_kwargs都不包含第一個視圖參數(request)。

Django會在調用視圖函數以前調用process_view方法。

它應該返回None或一個HttpResponse對象。 若是返回None,Django將繼續處理這個請求,執行任何其餘中間件的process_view方法,而後在執行相應的視圖。 若是它返回一個HttpResponse對象,Django不會調用對應的視圖函數。 它將執行中間件的process_response方法並將應用到該HttpResponse並返回結果。

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):
    def process_request(self, request):
        print("MD1裏面的 process_request")
    def process_response(self, request, response):
        print("MD1裏面的 process_response")
        return response
    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__) #就是url映射到的那個視圖函數,也就是說每一箇中間件的這個process_view已經提早拿到了要執行的那個視圖函數
        #ret = view_func(request) #提早執行視圖函數,不用到了上圖的試圖函數的位置再執行,若是你視圖函數有參數的話,能夠這麼寫 view_func(request,view_args,view_kwargs) 
        #return ret  #直接就在MD1中間件這裏這個類的process_response給返回了,就不會去找到視圖函數裏面的這個函數去執行了。

class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2裏面的 process_request")
        pass

    def process_response(self, request, response):
        print("MD2裏面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)
MD2裏面的 process_request
MD1裏面的 process_request
-------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x000001DE68317488> index
-------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x000001DE68317488> index
app01 中的 index視圖
MD1裏面的 process_response
MD2裏面的 process_response

process_exception

process_exception(self, request, exception)

兩個參數:
1.一個HttpRequest對象
2.一個exception是視圖函數異常產生的Exception對象。

這個方法只有在視圖函數中出現異常了才執行,它返回的值能夠是一個None也能夠是一個HttpResponse對象。若是是HttpResponse對象,Django將調用模板和中間件中的process_response方法,並返回給瀏覽器,不然將默認處理異常。若是返回一個None,則交給下一個中間件的process_exception方法來處理異常。它的執行順序也是按照中間件註冊順序的倒序執行。

def index(request):
    print("app01 中的 index視圖")
    raise ValueError("呵呵")
    return HttpResponse("O98K")
from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print("MD1裏面的 process_request")

    def process_response(self, request, response):
        print("MD1裏面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD1 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD1 中的process_exception")


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print("MD2裏面的 process_request")
        pass

    def process_response(self, request, response):
        print("MD2裏面的 process_response")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("-" * 80)
        print("MD2 中的process_view")
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception)
        print("MD2 中的process_exception")
MD1裏面的 process_request
MD2裏面的 process_request
--------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x0000022C09727488> index
--------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x0000022C09727488> index
app01 中的 index視圖
呵呵
MD2 中的process_exception
MD2裏面的 process_response
MD1裏面的 process_response


#注意,這裏並無執行MD2的process_exception方法,由於MD1中的process_exception方法直接返回了一個響應對象。

process_template_response

process_template_response(self, request, response)

參數:
1.一個HttpRequest對象
2.response是TemplateResponse對象(由視圖函數或者中間件產生)。

process_template_response是在視圖函數執行完成後當即執行,可是它有一個前提條件,那就是視圖函數返回的對象有一個render()方法(或者代表該對象是一個TemplateResponse對象或等價方法)。
def index(request):
    print("app01 中的 index視圖")
  #raise ValueError('出錯啦') 
    def render():
        print("in index/render")  
        #raise ValueError('出錯啦') #至於render函數中報錯了,那麼會先執行process_template_response方法,而後執行process_exception方法,若是是在render方法外面報錯了,那麼就不會執行這個process_template_response方法了。
        return HttpResponse("O98K") #返回的將是這個新的對象
        #raise ValueError('出錯啦') 將報錯放到這個位置不會報錯
    rep = HttpResponse("OK")
    rep.render = render
    return rep

3.3 登錄認證之中間件

view.py

from django.shortcuts import render,HttpResponse,redirect

def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    else:
        name = request.POST.get('name')
        password = request.POST.get('password')
        if name == 'liu' and password == '123':
            request.session['is_login'] = True
            return redirect('index')
        else:
            return redirect('login')

def index(request):
    return render(request,'index.html')

mymiddleware.py

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse,render,redirect

class MD1(MiddlewareMixin):
    white_list = ['/login/']
    def process_request(self,request):
        print('請求來了')
        path = request.path
        if  path not in self.white_list:
            status = request.session.get('is_login')
            if not status:
                return redirect('login')

    def process_response(self,request,response):
        print('響應走了')
        return response

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>登陸頁面</h1>
<form action="" method="post">
    {% csrf_token %}
用戶名:<input type="text" name="name">     <!--input標籤記得寫name-->
密碼:<input type="text" name="password">
<button class="submit">提交</button>
</form>
</body>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script></script>
</html>

4.多表圖書管理系統總結

1.靜態文件引入

{% load static %}   <!--static是關鍵字不能修改-->

<script src="{% static 'js/jquery.js' %}"></script>
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
<script src="{% static 'sw/sweetalert.min.js' %}"></script>

2.查看一本書的所有做者信息的高階寫法

原寫法jquery

show_book.htmlgit

<td>
    {% for author_obj in book_obj.authors.all %}
        {{ author_obj.name }}
        {% if forloop.last %}
    
        {% else %}
        ,
        {% endif %}
        {% endfor %}
</td>

初步高階github

models.pyajax

class Book(models.Model):
    """
    書籍表
    """
    ...
    def get_authors_name(self):

        authors = self.authors.all()
        name_list = []
        for i in authors:
            name_list.append(i.name)
       
        return ','.join(name_list)

show_book.htmlsql

{{ book_obj.get_authors_name }}

高階

models.py

class Book(models.Model):
    """
    書籍表
    """
    ...
    return ','.join(name_list)

show_book.html

{{ book_obj.get_authors_name }}

3.前端給後端傳數據的第二種方式

<a href="{% url 'delbook' %}?book_id={{ book_obj.pk }}" class="btn btn-danger">刪除</a>
def delbook(request):
    book_id = request.GET.get('book_id')
    models.Book.objects.filter(pk=book_id).delete()
    return redirect('showbooks')

4.刪除書籍 ---ajax版

<script>
$('.delete').on('click',function(){
    var th = $(this);
    var book_id = $(this).attr('book_id');
    console.log(book_id);
        $.ajax({
        url:{% url 'remove_book' %},
        type:'post',
        data:{book_id:book_id,csrfmiddlewaretoken: "{{ csrf_token }}"},
        success:function(res){
            if (res.status === 1){
                th.parent().parent().remove();
            }
        }
})})
</script>
def remove_book(request):
    book_id = request.POST.get('book_id')
    print(book_id)
    book_obj = models.Book.objects.get(id=book_id)
    book_obj.delete()
    data = {"status":1}
    return JsonResponse(data)
相關文章
相關標籤/搜索