form表单使用(博客系统的登陆验证,注册)
先从小的实例来看form的用法
登陆验证实例,来看form的常规用法
1. forms.py
# 用于登陆验证验证
from django.core.validators import RegexValidator 支持正则
# 登陆验证手动触发错误对象
from django.core.exceptions import ValidationError # 登陆规则
class loginform(Form):
name = fields.CharField(
required=True,
min_length=3,
max_length=18,
error_messages={
'required':'用户不能为空',
'min_length':'用户长度不能小于3',
'max_length':'用户长度不能大于18',
}
)
pwd = fields.CharField(
required=True,
min_length=3,
max_length=18,
error_messages={
'required': '用户不能为空',
'min_length': '用户长度不能小于3',
'max_length': '用户长度不能大于18',
'invalid':'密码格式错误', #自定义错误,优先级高
},validators=[RegexValidator('\d+','只能是数字',code)] #只能是数字也是报错信息,不过优先级低,也就是说如果用户输入非数字,那么提示invalid错误,如果invalid没有,那么报‘只能是数字’错误,code就是给invalid重新命名而已,没有什么用处,可以不写) # from扩展,可以直接在里面进行数据库操作,场景注册,局部钩子,博客系统注册,详细介绍了用法,见下文#######
def clean_name(self):
# 验证可以直接写在这里,进行验证,返回可以是任意类型,重新赋值给clean_date里面的user
user = self.cleaned_data['name']
is_exsit = models.UserInfo.objects.filter(name=user).count()
if not is_exsit:
raise ValidationError('用户名不存在')
return user def clean_pwd(self):
# 这里可以匹配数据库其他校验,返回可以是任意类型,重新赋值给clean_date里面的pwd
return True
2. views.py
def login(request):
if request.method=='GET':
form = loginform()
return render(request,'login.html',{'form':form})
elif request.method=='POST':
form = loginform(request.POST) # 前端提交数据给form
# 规则验证
if form.is_valid():
# 数据库验证
print('name',form.cleaned_data['name'])
user_obj = models.UserInfo.objects.filter(**form.cleaned_data).first()
if not user_obj:
form.add_error('pwd',ValidationError('用户名或者密码错误')) #当你符合格式,但是数据库没有的时候就会报错,跟局部钩子触发错误是一样的
return render(request,'login.html',{'form':form})
else:
print(form.cleaned_data['name'])
work_boj = models.Workers.objects.filter(utow__name=form.cleaned_data['name'], utow__pwd=form.cleaned_data['pwd']).first()
work = work_boj.workname
request.session[settings.USEROBJ] = {'username': user_obj.name, 'work': work}
return redirect('/index/')
else:
return render(request,'login.html',{'form':form})
else:
return HttpResponse('访问请求非get,post')
3. login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Title</title>
</head>
<body>
<form method="POST">
{% csrf_token %}
<p>{{ form.username }} {{ form.errors.username.0 }} </p>
<p>{{ form.password }} {{ form.errors.password.0 }} </p>
<input type="submit" value="提交" />
</form>
</body>
</html>
通过问卷的创建修改来看form的高级用法forms.fields.ChoiceField
主要了解下 forms.fields.ChoiceField(choices=[(1,'a'),(2,'b')]),和初始化数据
models.py
class UserInfo(models.Model):
"""
员工表
"""
name = models.CharField(max_length=32) def __str__(self):
return self.name class ClassInfo(models.Model):
"""
班级表
"""
name = models.CharField(max_length=32)
def __str__(self):
return self.name class Questionnaire(models.Model): # 问卷: 班级 :创建者
"""
问卷表 """
title = models.CharField(max_length=64)
cls = models.ForeignKey(to=ClassInfo)
creator = models.ForeignKey(to=UserInfo) def __str__(self):
return self.title
1. forms.py
from django import forms
from django.forms import widgets # 插件,可以插入些样式
from django.core.exceptions import ValidationError # 手动触发错误
from django.core.validators import RegexValidator # 支持正则 from app01 import models from django.forms.models import ModelChoiceField # 下拉框实时刷新第二种方法 class questionnaire_form(forms.Form): # 问卷规则
title = forms.fields.CharField(required=True,
error_messages={'required':'名称不能为空','invalid':'格式错误'},
widget=widgets.TextInput(attrs={'placeholder':'问卷名称',
'class':'form-control questionnaire_title'},)) # 其他框使用
# password = forms.fields.CharField(required=True, error_messages={'required': '密码不能为空'},
#widget=widgets.TextInput(attrs={'placeholder': '密码', 'class': 'form-control'})) # 不能为空
# email = forms.fields.EmailField(required=True, error_messages={'required': '邮箱不能为空', 'invalid': '邮箱格式错误'},
# widget=widgets.PasswordInput(attrs={'placeholder': '邮箱', 'class': 'form-control'})) # 不能为空,且邮箱格式
# text = forms.fields.CharField(required=True,error_messages={'required':'密码不能为空'},
# widget=widgets.Textarea(attrs={'class':'textatea'}))
# cls_list = fields.MultipleChoiceField(choices=[]) # 多选框,传过来的值,是列表
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
# self.fields['cls_list'].choices = models.ClassList.objects.values_list('id', 'caption') # 第一种实时刷新,通过重构init方法,不需要models的str方法
# cls_id = forms.fields.ChoiceField(choices=[])
# creator_id = forms.fields.ChoiceField(choices=[])
# def __init__(self,*args,**kwargs):
# super().__init__(*args,**kwargs)
# 不需要重启,修改后提交后,再点进来可以保证修改完成
# self.fields['cls_id'].choices= models.ClassInfo.objects.all().values_list('id','name')
# self.fields['creator_id'].choices = models.UserInfo.objects.all().values_list('id','name') # 第二种实时刷新,需要models里面的str方法,不然下拉框都是对象,访问数据库因为返回的是对象
cls_id = ModelChoiceField(queryset=models.ClassInfo.objects.all())
creator_id = ModelChoiceField(queryset=models.UserInfo.objects.all()) # 局部钩子
def clean_title(self): # 针对添加的时候,如果有questionnaire_title,就存在,没有可以正常进行
questionnaire_title = models.Questionnaire.objects.filter(title=self.cleaned_data.get('title')) # 前端传来的数据保存在clean_data里
if not questionnaire_title:
return self.cleaned_data.get('title')
else:
raise ValidationError('用户名已经存在') # 触发错误
2. views.py
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from .forms import *
from app01 import models def questionnaire_list(request):
'''
问卷首页,格式:8000/questionnaire首页,
:param request:
:param questionnaire_id:
:return:
'''
questionnaire_list = models.Questionnaire.objects.all() # 所有问卷
return render(request, "questionnaire_list.html", {'questionnaire_list':questionnaire_list}) def add_questionnaire_obj(request,**kwargs):
'''
添加问卷
:param request:
:param kwargs:
:return:
'''
if request.method == 'GET':
form = questionnaire_form()
return render(request, 'add_questionnaire_obj.html',{'form':form})
elif request.method == 'POST':
form = questionnaire_form(request.POST)
print(request.POST)
# 校验
if form.is_valid():
print(form.cleaned_data)
# 下拉框第二种实时更新方法,因为前端是queryset对象,所以需要把cleand_data数据重新更改一下
# form.cleaned_data['creator_id'] = form.cleaned_data['creator_id'].id
# form.cleaned_data['cls_id'] = form.cleaned_data['cls_id'].id
models.Questionnaire.objects.create(**form.cleaned_data)
return redirect('/questionnaire/')
else:
return render(request, 'add_questionnaire_obj.html', {'form': form}) def edit_questionnaire_obj(request,**kwargs):
'''
问卷对象,格式:8000/questionnaire/questionnaire_id,选中问卷编辑
:param request:
:param kwargs:
:return:
'''
questionnaire_id = kwargs.get('questionnaire_id') # 得到需要编辑的问卷的ID
if request.method == 'GET':
questionnaire_obj = models.Questionnaire.objects.filter(id=questionnaire_id).first() # 通过ID找到问卷对象
# form的实例化,initial初始化,适用于初始默认的值,
# form = questionnaire_form(),没有数据,只是可以在前端渲染标签,需要在FORM里面执行,例如TEXTIINPUT
# form = questionnaire_form(data=request.POST),有数据,并且到FORM里面进行验证
# 初始化的值,initial={'对象字段名称':,'对象字段,如果是关联字段加上ID,也就是数据库字段是什么,就是什么':}
# 初始化的字段名称最好跟MODELS的一样,FORM验证最好也是一样,前端也是一样,这样确保可以正常 ########### 注意
form = questionnaire_form(initial={"title":questionnaire_obj.title, "cls_id":questionnaire_obj.cls_id,"creator_id":questionnaire_obj.creator_id}) # 默认值
return render(request, "edit_questionnaire_obj.html", {'form': form})
if request.method == 'POST':
form =questionnaire_form(data=request.POST)
if form.is_valid():
print(form.cleaned_data)
print(form.errors)
models.Questionnaire.objects.filter(id=questionnaire_id).update(**form.cleaned_data)
return redirect('/questionnaire/')
else:
return render(request, 'edit_questionnaire_obj.html', {'form': form})
3. questionnaire_obj.html
<form action="" method="post">
{% csrf_token %}
<p>问卷调查名称:{{ form.title }}</p>
<p>选择班级:{{ form.cls_id }}</p>
<p>选择创建者:{{ form.creator_id }}</p>
<input type="submit" value="提交">
</form>
博客系统注册,读完肯定清晰明了,注意这里面有全局钩子的用法,
针对from.error下的__all__
models结构如下
class UserInfo(AbstractUser):
"""
用户信息
"""
nid = models.AutoField(primary_key=True)
nickname = models.CharField(verbose_name='昵称', max_length=32)
telephone = models.CharField(max_length=11, null=True, unique=True)
avatar = models.FileField(upload_to='avatar/',default="/avatar/default.png")
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
blog = models.OneToOneField(to='Blog', to_field='nid',null=True) def __str__(self):
return self.username
forms
from django import forms
from django.forms import widgets from . models import UserInfo
from django.core.exceptions import NON_FIELD_ERRORS,ValidationError # 手动触发错误 class RegForm(forms.Form): # 子类
# widget 默认情况下,CharField 具有一个TextInput 在HTML 中生成一个<input type="text">
# attrs 可以对input标签添加属性
def __init__(self,request,*args,**kwargs): # 派生方法
super().__init__(*args,**kwargs)
self.request = request # 派生属性
user = forms.CharField(min_length=5,max_length=12,required=True, # 规则
error_messages={'min_length':'最小长度5','max_length':'最大长度12','required':'不能为空'}, # 错误信息
widget = widgets.TextInput(attrs={'class':'form-control','placeholder':'username'})) # 生成标签,标签属性 pwd = forms.CharField(required=True,error_messages={'required':'不能为空'},widget = widgets.PasswordInput(attrs={'class':'form-control','placeholder':'password'})) repeat_pwd = forms.CharField(required=True,error_messages={'required':'不能为空'},widget = widgets.PasswordInput(attrs={'class':'form-control','placeholder':'repeat_password'})) email = forms.EmailField(required=True,error_messages={'invalid':'格式错误','required':'不能为空'},
# 生成一个EmailInput <input type="input">
widget = widgets.EmailInput(attrs={'class':'form-control','placeholder':'email','required':'不能为空'})) valid_code = forms.CharField(required=True,error_messages={'required':'不能为空'},widget = widgets.TextInput(attrs={'class':'form-control','placeholder':'valid_code'})) # 局部钩子,针对user的验证
def clean_user(self):
user = UserInfo.objects.filter(username=self.cleaned_data.get('user'))
if not user:
return self.cleaned_data.get('user')
else:
raise ValidationError('用户名已经存在') # 局部钩子,针对pwd的验证
def clean_pwd(self):
pwd = self.cleaned_data.get('pwd')
if pwd.isdigit() or pwd.isalpha():
raise ValidationError('不能是纯数字或者纯字母')
else:
return pwd # 局部钩子,针对验证码的验证
def clean_valid_code(self):
val = self.cleaned_data.get('valid_code')
if val.upper() == self.request.session.get('valid_code_str').upper():
return val
else:
raise ValidationError('验证码错误') # 全局钩子,针对全局上的验证,注意,先走局部后走全局
def clean(self):
if self.cleaned_data.get('pwd'):
if self.cleaned_data.get('pwd') == self.cleaned_data.get('repeat_pwd'):
return self.cleaned_data
else:
raise ValidationError('俩次密码不一致') # 正确信息保存在,clean.data
# 错误信息保存在,clean.error
1. urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login_in),
url(r'^register/', views.register),
]
2. views
from .forms import *
def register(request):
if request.is_ajax():
# 通过from表单验证
print(request.POST)
regForm = RegForm(request,request.POST)
regResponse = {'user':None,'errors':None}
if regForm.is_valid():
# 通过验证,可以注册
data = regForm.cleaned_data # 合法的表单数据,是以字典形式保存
user = data.get('user')
pwd = data.get('pwd')
email = data.get('email')
avatar_img = request.FILES.get('valid_img') #获取的文件对象
print(avatar_img)
print(type(avatar_img))
# user_obj = UserInfo.objects.filter(nid=2).update(avatar=avatar_img)
user_obj = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar_img)
regResponse['user'] = user_obj.username
else:
regResponse['errors'] = regForm.errors # regForm.errors 保存所有错误信息,包括__all__全局钩子错误
return JsonResponse(regResponse) regForm = RegForm(request) # 前端渲染,虽然没有数据,但是会渲染出标签来
return render(request,'register.html',{'regForm':regForm})
3. reg.html
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form>
{% csrf_token %}
<div class="form-group">
<label for="user">用户名:</label>
{# <input type="text" class="form-control" id="user" placeholder="User">#}
{{ regForm.user }} <span></span>
</div> <div class="form-group">
<label for="pwd">密码:</label>
{# <input type="password" class="form-control" id="pwd" placeholder="Password">#}
{{ regForm.pwd }} <span></span>
</div> <div class="form-group">
<label for="repeat_pwd">确认密码:</label>
{# <input type="password" class="form-control" id="repeat_pwd" placeholder="Repeat Password">#}
{{ regForm.repeat_pwd }} <span></span>
</div> <div class="form-group">
<label for="email">邮箱:</label>
{# <input type="email" class="form-control" id="email" placeholder="Email">#}
{{ regForm.email }} <span></span>
</div>
<div class="row">
<div class="col-md-6">
<input type="button" value="confirm register" class="btn btn-primary regBtn">
</div>
</div> </form> </div>
</div>
</div> <script>
{# AJAX提交注册表单,注册用户 #}
$(".regBtn").click(function () { var $formData = new FormData(); $formData.append('user',$('#id_user').val());
$formData.append('pwd',$('#id_pwd').val());
$formData.append('repeat_pwd',$('#id_repeat_pwd').val());
$formData.append('email',$('#id_email').val());
$formData.append('valid_code',$('#id_valid_code').val());
var file = $('#avatar_file')[0].files[0];
$formData.append('valid_img',file);
$formData.append('csrfmiddlewaretoken',$("[name='csrfmiddlewaretoken']").val()); $.ajax({
url: "/register/",
type: "POST",
data: $formData,
processData:false, // 不做转码或预处理
contentType:false, // 文件类型不做处理
success: function (data) {
if (data.user) {
location.href = '/login/'
}
else {
$('span').html('');
$(".form-group").removeClass("has-error");
console.log(data.errors); $.each(data.errors,function (i,j) {
$("#id_" + i).next().addClass('pull-right').css('color', 'red').html(j[0]).parent().addClass('has-error');
if(i == "__all__") {
$("#id_repeat_pwd").next().addClass("pull-right").css("color", "red").html(j[0]).parent().addClass("has-error");
$("#id_pwd").parent().addClass("has-error");
}
})
}
}
})
})
</script>
form表单使用(博客系统的登陆验证,注册)的更多相关文章
- 26种基于PHP的开源博客系统
26种基于PHP的开源博客系统 来源:本站原创 PHP学习笔记 以下列举的PHP开源Blog系统中,除了我们熟知的WordPress之外,大多都没有使用过,其中一些已经被淘汰,或者有人还在使用.除了做 ...
- 使用js提交form表单的两种方法
提交form表单的时候瑶族一些简单的验证,验证完后才能提交,避免无效提交. 1.当输入用户名和密码为空的时候,需要判断.这时候就用到了校验用户名和密码,这个需要在前端页面写:有两种方法,一种是用sub ...
- element-ui Form表单验证
element-ui Form表单验证规则全解 element的form表单非常好用,自带了验证规则,用起来很方便,官网给的案例对于一些普通场景完全没问题,不过一些复杂场景的验证还得自己多看文档摸索, ...
- 2.1博客系统 |基于form组件和Ajax实现注册登录
基于forms组件和Ajax实现注册功能 1 基于forms组件设计注册页面 --点击头像 === 点击input --头像预览: 修改用户选中的文件对象:获取文件对象的路径:修改img的src属性, ...
- 从零开始,搭建博客系统MVC5+EF6搭建框架(5),博客详情页、留言、轮播图管理、右侧统计博文
一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效 ...
- 【django之博客系统开发】
一.项目简介 使用django开发一套博客系统,参考博客园. 需求如下: 项目结构: 二.全部代码 from django.db import models # Create your models ...
- Django完整的开发一个博客系统
今天花了一些时间搭了一个博客系统,虽然并没有相关于界面的美化,但是发布是没问题的. 开发环境 操作系统:windows 7 64位 Django: 1.96 Python:2.7.11 IDE: Py ...
- web开发-Django博客系统
项目界面图片预览 项目代码github地址 项目完整流程 项目流程: 1 搞清楚需求(产品经理) (1) 基于用户认证组件和Ajax实现登录验证(图片验证码) (2) 基于forms组件和Ajax实现 ...
- PHP个人博客系统开发历程
声明: Author:GenialX GenialX's QQ:2252065614 GenialX's URL:胡旭博客 - www.ihuxu.com 一年多曾经的某一天,我在上交实验报告时,偶然 ...
随机推荐
- 使用springmvc时报错JSPs only permit GET POST or HEAD
两个地方需要注意:第一处在web.xml文件中不要忘记配置 <filter> <filter-name>HiddenHttpMethodFilter</filter-na ...
- vue2 遇到的问题汇集ing
1 .子路由 { path: '/order-list', //订单列表 name: "order-list", component(resolve) { require.ensu ...
- 图示:DOM元素各种位置属性
- yii2:模块
yii2:模块 模块不同于frontend/frontback单独的前后台单独的主题项目,模块不能单独部署,必须属于某个应用主体(如前后台:frontend/frontback). 模块置于modul ...
- Go-gin CORS 跨域中间件
原文:https://stackoverflow.com/questions/29418478/go-gin-framework-cors func CORSMiddleware() gin.Hand ...
- Updated: Database Partitioning with EBS Whitepaper
Partitioning allows a single database table and its associated indexes to be broken into smaller com ...
- Foundations of Qt Development 学习笔记 Part1 Tips1-50
1. 信号函数调用的时候仅仅会发送出信号,所以不需要执行 ,所以对于信号声明就行,但是不需要进行定义. 2. 只有槽函数可以声明为public,private,或者是protected的,而信号不行. ...
- Android 进阶9:进程通信之 AIDL 解析
读完本文你将了解: AIDL AIDL 生成文件分析 Stub Proxy AIDL 生成的内容小结 AIDL 的使用回顾 服务端 客户端 小结 手动写个 Binder 首先是定义跨进程接口实现 II ...
- 人生苦短之我用Python篇(基础)
Python简介 Python,是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于1991年. Python是纯粹的自由软件, ...
- IntelliJ IDEA下SVN配置及使用
一.在IDEA中使用SVN,首先需要下载安装 TortoiseSVN 插件. 打开 TortoiseSVN 下载地址,选择适合自己的系统类型下载. 接下来,进行安装即可.选择Modify,默认 com ...