# ajax结合sweetalert 1.下载源码 只需要到dist文件夹内的css和js即可 2.拷贝使用官网提供的案例代码 3.添加配置参数新增等待特效 <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h2 class="text-center">数据展示</h2> <table class="table table-striped table-hover"> <thead> <tr> <th>主键</th> <th>姓名</th> <th>年龄</th> <th>地址</th> <th>操作</th> </tr> </thead> <tbody> {% for user_obj in user_queryset %} <tr> <td>{{ user_obj.pk }}</td> <td>{{ user_obj.name }}</td> <td>{{ user_obj.age }}</td> <td>{{ user_obj.addr }}</td> <td> <a href="#" class="btn btn-primary btn-xs">编辑</a> <a href="#" class="btn btn-danger btn-xs deleteBtn" delete_id="{{ user_obj.pk }}">删除</a> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> <script> $('.deleteBtn').click(function () { let $deBtn = $(this); swal({ title: "你确定要删除吗?", text: "你要是真删 就准备好跑路吧!", type: "warning", showCancelButton: true, confirmButtonClass: "btn-danger", confirmButtonText: "牛逼, 准备跑路!", cancelButtonText: "怂货, 我真瞧不起你!", closeOnConfirm: false, closeOnCancel: false, showLoaderOnConfirm: true }, function(isConfirm) { if (isConfirm) { // 编写与后端交互的删除功能 let deleteId = $deBtn.attr('delete_id'); // 发送ajax请求 $.ajax({ url:'', type:'post', data:{'deleteId':deleteId}, success:function (args) { swal(args, "success"); $deBtn.parent().parent().remove() } }) } else { swal("咋又取消了", "你真的怂到家了!", "error"); } }); }) </script>
""" 钩子函数的含义其实就是在程序的执行过程中穿插额外的逻辑 校验用户名是否已存在 钩子函数之局部钩子(校验单个字段) 校验密码和确认面膜是否一致 钩子函数之全局钩子(校验多个字段) """ 钩子函数是数据经过了字段第一层参数校验之后才会执行
局部钩子
# 校验用户名是否存在 def clean_name(self): # 1.获取用户名 name = self.cleaned_data.get('name') # 2.判断用户名是否已存在 is_exist = models.User.objects.filter(name=name) if is_exist: # 3.提示信息 self.add_error('name', '用户名已存在') # 4.返回校验的字段name return name
全局钩子
# 校验两次密码是否一致 def clean(self): password = self.cleaned_data.get('password') re_password = self.cleaned_data.get('re_password') if not password == re_password: self.add_error('re_password', '两次密码不一致') # 全局钩子则返回self.cleaned_data return self.cleaned_data
```python from django.shortcuts import render,HttpResponse,redirect from django import forms class MyForm(forms.Form): name = forms.CharField(min_length=3, max_length=8, label='用户名', error_messages={ 'min_length': '用户名最少三位', 'max_length': '用户名做多八位', 'required': '用户名不能为空' }) password = forms.CharField(min_length=3, max_length=8, label='密码') re_password = forms.CharField(min_length=3, max_length=8, label='重复密码') age = forms.IntegerField(min_value=0, max_value=150, label='年龄') addr = forms.CharField(max_length=64, label='地址') email = forms.EmailField(label='邮箱') '''钩子函数是数据经过了字段第一层参数校验之后才会执行''' # 局部钩子(只校验一个字段) def clean_name(self): # 1.获取用户名 name = self.cleaned_data.get('name') # 2.判断用户名是否已存在 is_exist = models.User.objects.filter(name=name) if is_exist: # 3.提示信息 self.add_error('name', '用户名已存在') # 4.返回校验的字段name return name # 全局钩子(可校验多个字段) def clean(self): password = self.cleaned_data.get('password') re_password = self.cleaned_data.get('re_password') if not password == re_password: self.add_error('re_password', '两次密码不一致') # 全局钩子则返回self.cleaned_data return self.cleaned_data def register(request): form_obj = MyForm() if request.method == 'POST': form_obj = MyForm(request.POST) if form_obj.is_valid(): return HttpResponse('ok') return render(request, 'register.html', locals()) # 前端 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <form action="" method="post" novalidate> {% for foo in form_obj %} <p> {{ foo.label }} {{ foo }} <span style="color: red">{{ foo.errors.0 }}</span> </p> {% endfor %} <input type="submit" class="btn btn-success btn-block"> </form> </div> </div> </div> </body> </html>
min_length 最小长度 max_length 最大长度 label 字段名称 error_messages 错误提示 min_value 最小值 max_value 最大值 initial 默认值
validators 正则校验器 from django.core.validators import RegexValidator phone = forms.CharField( validators=[ RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')], )
widget 控制渲染出来的标签各项属性 password = forms.CharField( widget=forms.widgets.PasswordInput(attrs={'class':'form-control'}) ) # forms.widgets.控制type的类型(attrs=控制各项属性:class id ...)
choices 选择类型的标签内部对应关系 # radio gender = forms.ChoiceField( choices=((1, "男"), (2, "女"), (3, "保密")), label="性别", initial=3, widget=forms.widgets.RadioSelect() ) # 单选select hobby = forms.ChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=3, widget=forms.widgets.Select() ) # 多选select hobby1 = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=[1, 3], widget=forms.widgets.SelectMultiple() ) # 单选checkbox keep = forms.ChoiceField( label="是否记住密码", initial="checked", widget=forms.widgets.CheckboxInput() ) # 多选checkbox hobby2 = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=[1, 3], widget=forms.widgets.CheckboxSelectMultiple() )
# 文件类型 file = forms.FileField(label='文件', widget=forms.widgets.FileInput())
可以直接编写 也可以从数据库中获取 hobby = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), ) def __init__(self, *args, **kwargs): super(MyForm,self).__init__(*args, **kwargs) self.fields['hobby'].choices = models.Classes.objects.all().values_list('id','caption')
def is_valid(self): return self.is_bound and not self.errors # 查看类源码发现只要给类传参self.is_bound肯定是True @property def errors(self): if self._errors is None: self.full_clean() return self._errors # 查看了源码发现self._errors初始化就是None 所以肯定走full_clean方法 # 查看源码发现校验数据的整个过程内部都有异常处理机制 from django.core.exceptions import ValidationError raise ValidationError('用户名不存在 你个DSB')
forms组件主要配合models里面的模型类一起使用 但是模型类里的字段要在forms类中再写一遍 代码冗余 为了更好的结合forms与models的关系 便有了ModelForm(基于forms组件)
class MyUser(forms.ModelForm): class Meta: model = models.User # 指定关联的表 fields = '__all__' # 所有的字段全部生成对应的forms字段 labels = { 'name': '用户名', 'age': '年龄', 'addr': '地址', 'email': '邮箱' } widgets = { "name": forms.widgets.TextInput(attrs={"class": "form-control"}), } def reg(request): form_obj = MyUser() if request.method == 'POST': form_obj = MyUser(request.POST) if form_obj.is_valid(): # form_obj.save() # 新增数据 edit_obj = models.User.objects.filter(pk=5).first() form_obj = MyUser(request.POST, instance=edit_obj) # 是新增还是保存就取决于有没有instance参数 form_obj.save() # 编辑数据 return render(request, 'reg.html', locals())
# cookie简介 早期的互联网应用程序都是不保存用户状态的,所有人发送请求返回的都是相同的页面 现如今几乎所有的应用程序都可以保存用户状态!!!>>>:如何实现的??? HTTP协议四大特性之一:无状态 让服务端知道你是谁的方式很单一>>>:携带用户名和密码(身份标识) 每次操作之前都需要输入用户名和密码 当你成功登录之后浏览器会在本地帮你保存用户名和密码 每次操作浏览器自动发送用户名和密码 cookie本质 指代服务端让客户端保存的数据(存储在客户端上与用户信息相关的数据) '''简单的记忆:cookie就是存在客户端的东西''' # session简介 早期的cookie是直接存储的用户明文相关信息 不安全 用户登录成功之后 服务端生成一个随机字符串 返回给客户端保存 之后客户端每次发请求携带该随机字符串 服务端获取之后比对后台数据 eg: 服务端 随机字符串1 用户数据1 随机字符串2 用户数据2 随机字符串3 用户数据3 客户端 随机字符串1、随机字符串2、随机字符串3 session本质 指代服务端保存的跟用户信息相关的数据 '''简单的记忆:session就是存在服务端的东西''' """ 1.session的工作必须依赖于cookie 2.客户端也有权拒绝保存数据 """ ps:针对身份标识问题有很多方式 cookie和session是最基本的 token、jwt...
# 视图函数返回值 return HttpResonse() return render() return redirect() ... 不直接返回对象 而是先用变量名指代 然后操作对象方法 res = HttpResonse() return res res = render() return res res = redirect() return res # 基本使用 res.set_cookie() # 设置 res.COOKIE.get() # 获取 # 有很多视图函数需要添加登录认证 有时候又需要取消登录认证 装饰器 # 用户登录之后跳转到用户登录之前想要访问的页面 利用url问号携带参数
def login_auth(func_name): def inner(request, *args, **kwargs): if request.COOKIES.get('name'): res = func_name(request, *args, **kwargs) return res else: return redirect('/login/') return inner @login_auth def home(request): # if request.COOKIES.get('name'): # return HttpResponse('登录用户才能进入home页面') # return redirect('/login/') return HttpResponse('登录用户才能进入home页面') @login_auth def index(request): # if request.COOKIES.get('name'): # return HttpResponse("登录用户才能进入index页面") # return redirect('/login/') return HttpResponse('登录用户才能进入index页面') @login_auth def func(request): # if request.COOKIES.get('name'): # return HttpResponse('登录用户才能进入的func页面') # return redirect('/login/') return HttpResponse('登录用户才能进入的func页面')