forms组件钩子函数、字段参数、字段类型、cookie与session简介
ajax结合sweetalert使用删除功能
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<meta name="viewport" content="width=device-width, initial-scale=1">
{# <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>#}
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}">
<script src="{% static 'dist/sweetalert.js' %}">script>
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}">script>
<style>
.sweet-alert h2{
padding-top: 10px;
}
style>
head>
<body>
<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>
body>
html>
html代码
def user_list(request): if request.is_ajax(): if request.method == 'POST': delete_id = request.POST.get('deleteId') models.User.objects.filter(pk=delete_id).delete() return HttpResponse('数据以删除') user_queryset = models.User.objects.all() return render(request, 'user_list.html', locals())函数代码
# 局部钩子:校验用户名是否已存在(一次性只能勾一个人) '''钩子函数是数据经过了字段第一层参数校验之后才会执行''' def clean_name(self): # 自动生成的函数名 专门用于对name字段添加额外的校验规则 # 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): # 1.获取多个字段数据 password = self.cleaned_data.get('password') confirm_password = self.cleaned_data.get('confirm_password') if not password == confirm_password: self.add_error('confirm_password', '两次密码不一致 你个傻帽!!!') # 最后将整个数据返回 return self.cleaned_data
min_length 最小长度 max_length 最大长度 label 字段名称 error_messages 错误提示 min_value 最小值 max_value 最大值 initial 默认值 validators 正则校验器
phone = forms.CharField( validators=[ RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')], )
widget 控制渲染出来的标签各项属性 password = forms.CharField(min_length=3, max_length=8, label='密码',
widget=forms.widgets.PasswordInput(attrs={'class':'form-control'}) )
forms.widgets.控制type的类型(attrs=控制各项属性:class id ...)
choices 选择类型的标签内部对应关系 可以直接编写 也可以从数据库中获取 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')
""" 看源码可以提升编程能力(CBV源码) 也可以从中获取出更多的使用方式(JsonResponse) """ 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')
Django Form所有内置字段
Field required=True, 是否允许为空 widget=None, HTML插件 label=None, 用于生成Label标签或显示内容 initial=None, 初始值 help_text='', 帮助信息(在标签旁边显示) error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'} validators=[], 自定义验证规则 localize=False, 是否支持本地化 disabled=False, 是否可以编辑 label_suffix=None Label内容后缀 CharField(Field) max_length=None, 最大长度 min_length=None, 最小长度 strip=True 是否移除用户输入空白 IntegerField(Field) max_value=None, 最大值 min_value=None, 最小值 FloatField(IntegerField) ... DecimalField(IntegerField) max_value=None, 最大值 min_value=None, 最小值 max_digits=None, 总长度 decimal_places=None, 小数位长度 BaseTemporalField(Field) input_formats=None 时间格式化 DateField(BaseTemporalField) 格式:2015-09-01 TimeField(BaseTemporalField) 格式:11:12 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 DurationField(Field) 时间间隔:%d %H:%M:%S.%f ... RegexField(CharField) regex, 自定制正则表达式 max_length=None, 最大长度 min_length=None, 最小长度 error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'} EmailField(CharField) ... FileField(Field) allow_empty_file=False 是否允许空文件 ImageField(FileField) ... 注:需要PIL模块,pip3 install Pillow 以上两个字典使用时,需要注意两点: - form表单中 enctype="multipart/form-data" - view函数中 obj = MyForm(request.POST, request.FILES) URLField(Field) ... BooleanField(Field) ... NullBooleanField(BooleanField) ... ChoiceField(Field) ... choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),) required=True, 是否必填 widget=None, 插件,默认select插件 label=None, Label内容 initial=None, 初始值 help_text='', 帮助提示 ModelChoiceField(ChoiceField) ... django.forms.models.ModelChoiceField queryset, # 查询数据库中的数据 empty_label="---------", # 默认空显示内容 to_field_name=None, # HTML中value的值对应的字段 limit_choices_to=None # ModelForm中对queryset二次筛选 ModelMultipleChoiceField(ModelChoiceField) ... django.forms.models.ModelMultipleChoiceField TypedChoiceField(ChoiceField) coerce = lambda val: val 对选中的值进行一次转换 empty_value= '' 空值的默认值 MultipleChoiceField(ChoiceField) ... TypedMultipleChoiceField(MultipleChoiceField) coerce = lambda val: val 对选中的每一个值进行一次转换 empty_value= '' 空值的默认值 ComboField(Field) fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式 fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) MultiValueField(Field) PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField) input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y'] input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中 path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True, 允许文件 allow_folders=False, 允许文件夹 required=True, widget=None, label=None, initial=None, help_text='' GenericIPAddressField protocol='both', both,ipv4,ipv6支持的IP格式 unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用 SlugField(CharField) 数字,字母,下划线,减号(连字符) ... UUIDField(CharField) uuid类型Django Form所有内置字段
""" 看源码可以提升编程能力(CBV源码) 也可以从中获取出更多的使用方式(JsonResponse) """ 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() # 获取 # 有很多视图函数需要添加登录认证 有时候又需要取消登录认证 装饰器