目录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)