1.Django Form表单的作用
Django用Form类描述html表单,帮助或简化操作
1、接收和处理用户提交的数据
可检查提交的数据
可将数据转换成Python的数据类型
2、可自动生成html代码
上次登录界面是写在了博客页面,这次应该把它提取出来作为一个公共页面,点击登录时进入这个公共页面,那么上次使用的登录后跳转到
登录前的博客页面得进行修改,因为上次记录的时本页面的链接,此时进入了一个新的登录页面,上次的方法会跳转到登录页面。
我们要进入登录之前的页面,最好把这个页面传进来,我们就知道该怎么跳转,有2种方式,一种是GET方式,链接打个?写个参数;POST是在登录表单中
加入一个字段,写刚才的链接。此时采用GET方式。
对表单验证通过时,获取用户名,密码,再验证用户名,密码的正确性,正确时成功登陆,错误时失败登陆
登录成功时返回登录前的博客页面:
<a href="{% url 'login' %}?from={{ request.get_full_path }}">登录</a>
from等于一个链接
通过GET方式传了一个参数
在views的login方法中,获取from参数,如果没传返回首页。
return redirect(request.GET.get('from'), reverse('home'))
登录不成功时,返回用户名或密码错误信息,也可以用错误页面的方法,但是跳来跳去不是很好,可以利用djangofrom本身有个错误集合,login_form本身包含一个错误集,
可以把错误信息加到错误集,第一个是字段,可能是用户名也可能是密码错误,写None,第二个是错误信息。信息有了后返回form,此时form中就有了错误信息,就会自动显示到
前端模版页面。
login_form.add_error(None, '用户名或密码不正确')
context = {}
context['login_form'] = login_form
return render(request, 'login.html', context)
前端出现的错误显示代码
<ul class="errorlist nonfield"><li>用户名或密码不正确</li></ul>
验证不通过时,也会携带错误信息,之后返回form
context = {}
context['login_form'] = login_form
return render(request, 'login.html', context)
最后代码,登陆逻辑
def login(request): '''username = request.POST.get('username','') password = request.POST.get('password','') user = auth.authenticate(request, username=username, password=password) referer = request.META.get('HTTP_REFERER', reverse('home')) if user is not None: auth.login(request, user) return redirect(referer) else: return render(request,'error.html',{'message':'用户名或密码不正确'})''' if request.method == 'POST': login_form = LoginForm(request.POST) #提交相关数据进行初始化 if login_form.is_valid(): #验证数据是否有效 username = login_form.cleaned_data['username'] #经过验证的数据可以通过clean_data获取 password = login_form.cleaned_data['password'] user = auth.authenticate(request, username=username, password=password) if user is not None: auth.login(request, user) return redirect(request.GET.get('from'), reverse('home')) else: login_form.add_error(None, '用户名或密码不正确') else: login_form = LoginForm() context = {} context['login_form'] = login_form return render(request,'login.html',context)
感觉DjangoForm对比Html就是,把前端页面写的表单移到了forms文件中,通过views实例化后传到前端页面;forms中还可以进行验证,如用户名密码验证,
字段验证。执行is_valid()的时候就会进入forms中的一些clean方法中。在forms中经过is_valid()验证后的数据可以通过cleaned_data获取。
我们可以吧验证的代码都放到forms中,这里是验证用户名和密码是否正确,就可以把views中的验证删除。使得views更加简洁。
from django import forms from django.contrib import auth class LoginForm(forms.Form): username = forms.CharField(label='用户名') password = forms.CharField(label='密码', widget=forms.PasswordInput) def clean(self): username = self.cleaned_data['username'] password = self.cleaned_data['password'] user = auth.authenticate(username=username, password=password) if user is None: raise forms.ValidationError('用户名或密码不正确') else: self.cleaned_data['user'] = user return self.cleaned_data
优化views
if request.method == 'POST': login_form = LoginForm(request.POST) #提交相关数据进行初始化 if login_form.is_valid(): #验证数据是否有效 user = login_form.cleaned_data['user'] auth.login(request, user) return redirect(request.GET.get('from'), reverse('home')) else: login_form = LoginForm() context = {} context['login_form'] = login_form return render(request,'login.html',context)
前端页面的显示也可以用bootsrap进行优化
{#先弄个容器,在弄个行,之后4列宽度,偏移4行到中间,之后把form放到一个带标题的面板里#} {#为了去掉冒号需要遍历login_form,之后把他的的label也显示出来,再进行错误的显示;若要对输入框进行美化可以在forms中优化#} {% block content %} <div class="container"> <div class="row"> <div class="col-xs-4 col-xs-offset-4"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">登录</h3> </div> <div class="panel-body"> <form action="" method="POST"> {% csrf_token %} {% for field in login_form %} <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} <p class="text-danger">{{ field.errors.as_text }}</p> {% endfor %} <span class="pull-left text-danger">{{ login_form.non_field_errors }}</span> <input type="submit" value="登录" class="btn btn-primary pull-right"> </form> </div> </div> </div> </div> </div>
#优化输入框
class LoginForm(forms.Form): username = forms.CharField(label='用户名', widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'请输入用户名'})) password = forms.CharField(label='密码', widget=forms.PasswordInput(attrs={'class':'form-control', 'placeholder':'请输入密码'}))
登录写完了,再写注册
依次写forms,urls,前端,views。
forms
class RegForm(forms.Form): username = forms.CharField(label='用户名', max_length=30, min_length=3, widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'请输入3-30位用户名'})) email = forms.EmailField(label='邮箱', widget=forms.EmailInput(attrs={'class':'form-control', 'placeholder':'请输入邮箱'})) password = forms.CharField(label='密码', min_length=6, widget=forms.PasswordInput(attrs={'class':'form-control', 'placeholder':'请输入密码'})) password_again = forms.CharField(label='密码', min_length=6, widget=forms.PasswordInput(attrs={'class':'form-control', 'placeholder':'再输入一次密码'})) def clean_username(self): username = self.cleaned_data['username'] if User.objects.filter(username=username).exists(): raise forms.ValidationError('用户名已存在') return username def clean_email(self): email = self.cleaned_data['email'] if User.objects.filter(email=email).exists(): raise forms.ValidationError('邮箱已存在') return email def clean_password_again(self): password = self.cleaned_data['password'] password_again = self.cleaned_data['password_again'] if password != password_again: raise forms.ValidationError('两次输入的密码不一致') return password_again
urls
path('register/', views.register,name='register'),
前端
{% extends 'base.html' %} {% load staticfiles %} {% block title %} 我的网站|注册 {% endblock %} {% block nav_home_active %}active{% endblock %} {#先弄个容器,在弄个行,之后4列宽度,偏移4行到中间,之后把form放到一个带标题的面板里#} {#为了去掉冒号需要遍历reg_form,之后把他的的label也显示出来,再进行错误的显示;若要对输入框进行美化可以在forms中优化#} {% block content %} <div class="container"> <div class="row"> <div class="col-xs-4 col-xs-offset-4"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">注册</h3> </div> <div class="panel-body"> <form action="" method="POST"> {% csrf_token %} {% for field in reg_form %} <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} <p class="text-danger">{{ field.errors.as_text }}</p> {% endfor %} <span class="pull-left text-danger">{{ reg_form.non_field_errors }}</span> <input type="submit" value="登录" class="btn btn-primary pull-right"> </form> </div> </div> </div> </div> </div> {% endblock %}
views
def register(request): if request.method == 'POST': reg_form = RegForm(request.POST) #提交相关数据进行初始化 if reg_form.is_valid(): #验证数据是否有效,之后获取数据 username = reg_form.cleaned_data['username'] email = reg_form.cleaned_data['email'] password = reg_form.cleaned_data['password'] #创建用户 user = User.objects.create_user(username,email,password) user.save() #登录用户 user = auth.authenticate(username=username,password=password) auth.login(request,user) #跳转到进入注册页面之前的路径 return redirect(request.GET.get('from'), reverse('home')) else: reg_form = RegForm() context = {} context['reg_form'] = reg_form return render(request,'register.html',context)