先从小的实例来看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表单使用(博客系统的登陆验证,注册)的更多相关文章

  1. 26种基于PHP的开源博客系统

    26种基于PHP的开源博客系统 来源:本站原创 PHP学习笔记 以下列举的PHP开源Blog系统中,除了我们熟知的WordPress之外,大多都没有使用过,其中一些已经被淘汰,或者有人还在使用.除了做 ...

  2. 使用js提交form表单的两种方法

    提交form表单的时候瑶族一些简单的验证,验证完后才能提交,避免无效提交. 1.当输入用户名和密码为空的时候,需要判断.这时候就用到了校验用户名和密码,这个需要在前端页面写:有两种方法,一种是用sub ...

  3. element-ui Form表单验证

    element-ui Form表单验证规则全解 element的form表单非常好用,自带了验证规则,用起来很方便,官网给的案例对于一些普通场景完全没问题,不过一些复杂场景的验证还得自己多看文档摸索, ...

  4. 2.1博客系统 |基于form组件和Ajax实现注册登录

    基于forms组件和Ajax实现注册功能 1 基于forms组件设计注册页面 --点击头像 === 点击input --头像预览: 修改用户选中的文件对象:获取文件对象的路径:修改img的src属性, ...

  5. 从零开始,搭建博客系统MVC5+EF6搭建框架(5),博客详情页、留言、轮播图管理、右侧统计博文

    一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效 ...

  6. 【django之博客系统开发】

    一.项目简介 使用django开发一套博客系统,参考博客园. 需求如下: 项目结构: 二.全部代码 from django.db import models # Create your models ...

  7. Django完整的开发一个博客系统

    今天花了一些时间搭了一个博客系统,虽然并没有相关于界面的美化,但是发布是没问题的. 开发环境 操作系统:windows 7 64位 Django: 1.96 Python:2.7.11 IDE: Py ...

  8. web开发-Django博客系统

    项目界面图片预览 项目代码github地址 项目完整流程 项目流程: 1 搞清楚需求(产品经理) (1) 基于用户认证组件和Ajax实现登录验证(图片验证码) (2) 基于forms组件和Ajax实现 ...

  9. PHP个人博客系统开发历程

    声明: Author:GenialX GenialX's QQ:2252065614 GenialX's URL:胡旭博客 - www.ihuxu.com 一年多曾经的某一天,我在上交实验报告时,偶然 ...

随机推荐

  1. 使用springmvc时报错JSPs only permit GET POST or HEAD

    两个地方需要注意:第一处在web.xml文件中不要忘记配置 <filter> <filter-name>HiddenHttpMethodFilter</filter-na ...

  2. vue2 遇到的问题汇集ing

    1 .子路由 { path: '/order-list', //订单列表 name: "order-list", component(resolve) { require.ensu ...

  3. 图示:DOM元素各种位置属性

  4. yii2:模块

    yii2:模块 模块不同于frontend/frontback单独的前后台单独的主题项目,模块不能单独部署,必须属于某个应用主体(如前后台:frontend/frontback). 模块置于modul ...

  5. Go-gin CORS 跨域中间件

    原文:https://stackoverflow.com/questions/29418478/go-gin-framework-cors func CORSMiddleware() gin.Hand ...

  6. Updated: Database Partitioning with EBS Whitepaper

    Partitioning allows a single database table and its associated indexes to be broken into smaller com ...

  7. Foundations of Qt Development 学习笔记 Part1 Tips1-50

    1. 信号函数调用的时候仅仅会发送出信号,所以不需要执行 ,所以对于信号声明就行,但是不需要进行定义. 2. 只有槽函数可以声明为public,private,或者是protected的,而信号不行. ...

  8. Android 进阶9:进程通信之 AIDL 解析

    读完本文你将了解: AIDL AIDL 生成文件分析 Stub Proxy AIDL 生成的内容小结 AIDL 的使用回顾 服务端 客户端 小结 手动写个 Binder 首先是定义跨进程接口实现 II ...

  9. 人生苦短之我用Python篇(基础)

    Python简介 Python,是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于1991年. Python是纯粹的自由软件, ...

  10. IntelliJ IDEA下SVN配置及使用

    一.在IDEA中使用SVN,首先需要下载安装 TortoiseSVN 插件. 打开 TortoiseSVN 下载地址,选择适合自己的系统类型下载. 接下来,进行安装即可.选择Modify,默认 com ...