引言:想使用python的flask框架搭建一个日料网站,主要包含web架构,静态页面,后台系统,交互,今天教你们实现后台登陆功能,比较简单。html
本节知识:表单标签,表单验证,数据查询,模板python
python环境:python2.7,flask,以及flask相关的库(没有列完,若是运行manage.py时提示未安装的库安装就ok了。)git
上节已经把admin(后台用户表)表建好了,再看看模型吧。github
-----models.pyweb
class Admin(db.Model): __tablename__ = 'admin' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True, index=True) password = db.Column(db.String(128)) ###权限 admin=1 1>2>3 power = db.Column(db.Integer) set_time = db.Column(db.DateTime) set_user = db.Column(db.Integer) email = db.Column(db.String(128)) phone = db.Column(db.String(128)) ''' def __init__(self, username=None, password=None, power=None,phone=phone): self.username = username self.password = password self.power = power self.phone = phone ''' def __repr__(self): return '<User %r>' % self.username, def check_user(self,username,password): obj = self.query.filter_by(username=username,password=password).first() return obj def check_user_aru(self,username): obj = self.query.filter_by(username=username).first() return obj def get_auser(self): obj = db.session.execute('select b.* ,a.username as set_user_name from admin as a ,admin as b where a.id =b.set_user ').fetchall() return obj
上面大部分是admin表的字段定义内容,下面的函数是我之后会用到的函数。sql
虽然字段有点多,不过咱们只须要用到username和password就好了,肯定了表单字段,接下来就要生成login页面。数据库
-----先在视图文件定义 views.py 这不是完整版,由于还须要定义表单类,下面的LoginForm 还未写出来。flask
@main.route('/admin/login', methods=['GET', 'POST']) def Alogin(): form = LoginForm() if request.method=='POST': if form.validate_on_submit(): username = form.username.data password = form.password.data ####查询数据 try: obj = Admin.check_user(Admin(),username, password) if obj: session['username'] = username session['userid'] = obj.id ###记入adminlog session['login_time'] = int(time.time()) login_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) ip = get_ip() log_list = AdminLog(username=username,userid=obj.id,login_time=login_time,ip=ip,email=obj.email, phone=obj.phone,power=obj.power,loginout_time='') db.session.add(log_list) db.session.commit() log_id = log_list.id session['log_id'] = log_id return redirect('/admin/') except: return render_template('admin/login.html',form=form,errors_info=u'用户名或密码错误!!') else: return render_template('admin/login.html',form=form,error=form.errors) else: if session.has_key('username'): return redirect('/admin/') return render_template('admin/login.html',form=form)
上述代码已经写出大概逻辑了,接下来是login.html以及_formhelpers1.html的内容session
-----login.html 只看表单部分就行了架构
{% from "_formhelpers.html" import render_field %} <form id="loginform" class="form-vertical" action="/admin/login" method="post"> {{ form.hidden_tag() }} <div class="control-group normal_text"> <h3><img src="{{url_for('static', filename='images/admin/logo.png')}}" alt="Logo" /></h3></div> <div class="control-group"> <div class="controls"> <div class="main_input_box"> <span class="add-on bg_lg"><i class="icon-user"></i></span>{{ render_field(form.username) }} </div> </div> </div> <div class="control-group"> <div class="controls"> <div class="main_input_box"> <span class="add-on bg_ly"><i class="icon-lock"></i></span>{{ render_field(form.password) }} </div> </div> </div> {% if errors_info %} <span style="margin-left:26px; color:red">{{ errors_info }}</span>{% endif %} <div class="form-actions"> <span class="pull-left"><a href="#" class="flip-link btn btn-info" id="to-recover">Lost password?</a></span> <span class="pull-right"><input type="submit" class="btn btn-success" value="Login"/> </span> </div> </form>
从_formhelpers1.html引入字段,赋值到form标签里面,这里须要注意_formhelpers1.html放置的路径,对应就ok了。
------_formhelpers1.html
{% macro render_field(field) %} {{ field(**kwargs)|safe }} {% if field.errors %} {% for error in field.errors %} <span for="required" generated="true" class="help-inline">{{ error }}</span> {% endfor %} {% endif %} {% endmacro %}
该文件的内容就是定义的表单标签,以及输出错误的信息(error)。
接下来上完整版views.py 加上LoginForm
class LoginForm(FlaskForm): username = StringField('Username', validators=[Length(min=3, max=25,message=u'请输入3-25个字符!')],render_kw={"placeholder": "username",}) password = PasswordField('Password',validators= [ Length(min=3, max=25,message=u'请输入4-25个字符!')], render_kw={"placeholder": "password",} ) class AuserForm(FlaskForm): username = StringField('username',validators=[Length(min=3, max=25,message=u'请输入3-25个字符!')],) password = PasswordField('password',validators= [ Length(min=3, max=25,message=u'请输入4-25个字符!')], ) repassword = PasswordField('repassword',validators= [ Length(min=3, max=25,message=u'请输入4-25个字符!')], ) email = StringField('email', validators=[Length(min=3, max=25,message=u'请输入3-25个字符!')],) phone = StringField('phone', validators=[Length(min=3, max=25,message=u'请输入3-25个字符!')],) power = SelectField('power',choices=[(2,u'管理帐户'),(3,u'普通帐户')],coerce=int) @main.route('/', methods=['GET', 'POST']) def index(): return render_template('index.html') @main.route('/admin/login', methods=['GET', 'POST']) def Alogin(): form = LoginForm() if request.method=='POST': if form.validate_on_submit(): username = form.username.data password = form.password.data ####查询数据 try: obj = Admin.check_user(Admin(),username, password) if obj: session['username'] = username session['userid'] = obj.id ###记入adminlog session['login_time'] = int(time.time()) login_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) ip = get_ip() log_list = AdminLog(username=username,userid=obj.id,login_time=login_time,ip=ip,email=obj.email, phone=obj.phone,power=obj.power,loginout_time='') db.session.add(log_list) db.session.commit() log_id = log_list.id session['log_id'] = log_id return redirect('/admin/') except: return render_template('admin/login.html',form=form,errors_info=u'用户名或密码错误!!') else: return render_template('admin/login.html',form=form,error=form.errors) else: if session.has_key('username'): return redirect('/admin/') return render_template('admin/login.html',form=form)
认真看下class LoinForm 怎么定义字段的照葫芦画瓢就ok了。
----------------------这是分割线----------------------------
没有报错的话如今打开页面是ok的
----先测试下,表单字段的验证有没有问题
当我直接点击登陆,没有填写字段名,确定是通不过验证的
符合class LoginForm 设置的错误信息,验证还有不少方式,网上查阅下资料便可。
----------接下来咱们来看看views.py 登陆的逻辑,基本大功告成了
@main.route('/admin/login', methods=['GET', 'POST'])##定义能够请求的方式 def Alogin(): form = LoginForm()##实例登陆类,传到页面 if request.method=='POST': ##提交方式 if form.validate_on_submit(): ##能够经过验证 username = form.username.data ##获取表单数据 password = form.password.data ####查询数据 try: obj = Admin.check_user(Admin(),username, password) ##开始查询 if obj: session['username'] = username session['userid'] = obj.id ###记入adminlog session['login_time'] = int(time.time()) login_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) ip = get_ip() log_list = AdminLog(username=username,userid=obj.id,login_time=login_time,ip=ip,email=obj.email, phone=obj.phone,power=obj.power,loginout_time='') db.session.add(log_list) db.session.commit() log_id = log_list.id session['log_id'] = log_id return redirect('/admin/') except: return render_template('admin/login.html',form=form,errors_info=u'用户名或密码错误!!') ##传入本身设置的error信息 else: return render_template('admin/login.html',form=form,error=form.errors) else: if session.has_key('username'): ##登陆时须要判断用户是否已经登录了,固然还有其余,别入不一样的ip继续登陆,就要把他挤下去等 return redirect('/admin/') return render_template('admin/login.html',form=form)
里面的check_user函数,正式models.py里面定义的
固然不定义在这里也能够,后期还须要规整,关于数据库的操做还有有些些麻烦,搞得我每次都想用原生sql来搞了,网上资料也老是对不上个人点,忧伤。
下次根据后台的功能,再分享下增删改查的操做,你们一块儿学习。
暂时没有把项目上传到github上面,之后我再传。