目錄css
1.https://github.com/lipis/bootstrap-sweetalert 在github下載css、js文件放到項目靜態文件夾中 2.在html頁面分別引入jquery、bootstrap文件,sweetalert是基於bootstrap實現 3.將代碼複製到script標籤中
$(".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") } } }) }); })
鎖: select * from book where id=1 for update; 事務: begin select * from book where id=1 for update; commit
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()
中間件顧名思義,是介於request與response處理之間的一道處理過程,相對比較輕量級,而且在全局上改變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配置項是一個列表,列表中是一個個字符串,這些字符串實際上是一個個類,也就是一個個中間件。
中間件能夠定義五個方法,分別是:(主要的是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有一個參數,就是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視圖
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返回
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(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(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(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
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')
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
<!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>
{% 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>
原寫法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 }}
<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')
<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)