个人学期总结
1.本人在这学期中学习了管理信息系统这门科目,这门科目主要讲解了基于Python的Flask框架web建设项目。学习用html元素制作web网页,观察常用网页的HTML元素,在实际的应用场景中,用已学的标签模仿制作。制作自己的导航条,认识css的盒子模型,用div等元素布局形成html文件。完成了登录与注册页面的html+css+js, 夜间模式的开启和关闭,制作网站网页共有元素的父模板html,包括顶部导航,中间区块划分,底部导航,底部说明等。汇总相关的样式形成独立的css文件,使用 js代码形成独立的js文件,形成完整的base.html+css+js。 后期,进行flask项目,理解flask项目主程序,使用装饰器,设置路径与函数之间的关系。加载静态文件,父模板的继承和扩展。连接mysql数据库,创建用户模型,通过用户模型,对数据库进行增删改查,完成登录、注册、发布评论等功能,继续对我们的项目进行完善。
2、总结Python+Flask+MysqL的web建设技术过程,标准如下:
- 即是对自己所学知识的梳理
- 也可作为初学入门者的简单教程
- 也可作为自己以后复习的向导
- 也是一种向外展示能力的途径
一.开发工具:主要工具有:pycharm64.exe + Python 3.6 64-bit + MySQL + Navicat for MySQL(辅助工具)
二.界面的实现:
1.导航条base.html,其他页面在编写的时候可以通过{% extends 'base.html' %}去调用
<!DOCTYPE HTML> <html> <head lang="en"> <meta charset="UTF-8"> <title>{% block title %}首页{% endblock %}</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous"> <script src="{{ url_for('static',filename='js/base.js') }}"></script> {% block head %}{% endblock %} <body background="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1514551681109&di=4e795153c9660db74ff06c1463180876&imgtype=0&src=http%3A%2F%2Fimg.ph.126.net%2FlCFW6F0A46eced8IjrhWOQ%3D%3D%2F2570148012361858430.jpg" style="background-repeat: no-repeat; background-size: 100% 100%; background-attachment: fixed;"> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item"><a class="navbar-brand" href="{{ url_for('index') }}">首页 </a></li> <li class="nav-item active"><a class="navbar-brand" href="{{ url_for('question') }}">问题 </a></li> <form action="{{url_for('search')}}" method="get" class="form-inline" > <input name="q" class="form-control mr-sm-2" type="search" placeholder="请输入关键字" > <button class="btn btn-outline-success my-2 my-sm-0" type="submit">搜索</button> </form> </ul> <nav class="navbar navbar-light bg-light"> {% if username %} <a class="navbar-brand" href="{{ url_for('usercenter',user_id=session.get('userid'),tag=1) }}">{{ session.get('user') }} </a> <a class="navbar-brand" href="{{ url_for('logout') }}">注销 </a> {% else %} <a class="navbar-brand" href="{{ url_for('login') }}">登陆 </a> <a class="navbar-brand" href="{{ url_for('regist') }}">注册 </a> {% endif %} <img src="{{ url_for('static',filename='image/on.jpg') }}" width="14" height="14"> </nav> </div> </nav> {% block main %} {% endblock %} <div class="copyRight" style="background:skyblue;text-align: center;position:fixed; left:0px; bottom:0px; width:100%; height:30px; z-index:9999"> Copyright huiyi版权所有 </div> <footer class="copyright"> </footer> </body> </html>
2.登陆页面(登录与注册页面的HTML+CSS+JS)
1通过用视图函数反转得到URL,{{url_for(‘login’)}},完成导航条里的链接。
(1)<script src="{{ url_for('static',filename='js/login.js') }}"></script>
(2)flask 从static文件夹开始寻找
(3)可用于加载css, js, image文件
2通过login.js实现(用户名6-12位,首字母不能是数字,只能包含字母和数字,密码6-12位,注册页两次密码是否一致)
3.对父模版的继承和扩展
(1)把一些公共的代码放在父模板中,避免每个模板写同样的内容。base.html
(2)子模板继承父模板 {% extends 'base.html’ %}
(3)父模板提前定义好子模板可以实现一些自己需求的位置及名称。
<title>{% block title %}{% endblock %}-MIS问答平台</title>
{% block head %}{% endblock %}
{% block main %}{% endblock %}
(4)子模板中写代码实现自己的需求。
{% block title %}登录{% endblock %}
{% extends 'base.html' %} {% block title %} 登录 {% endblock %} {% block head %} <link href="{{ url_for('static',filename='css/login.css') }}" rel="stylesheet" type="text/css"> <script src="{{ url_for('static',filename='js/login.js') }}"></script> {% endblock %} {% block main %} <br> <br> <br> <div class="login" > <h1>登录</h1> <form action="{{ url_for('login') }}" method="post"> <p><input id="umane"type="text" name="username" placeholder="请输入用户名"></p> <p><input id="upass"type="password" name="password" placeholder="请输入密码"></p> <div id="error_box"><br></div> <p class="submit"> <input onclick="return myLogin()" type="submit" name="commit" value="登录"> <input onclick=window.alert("是否取消登录?") type="submit" name="commit" value="取消"> </p> </form> </div> {% endblock %}
3.评论页面
三.Flask项目
1.使用Flask中render_template,用不同的路径,返回首页、登录员、注册页。
2.实现注册
(1)js文件: onclick函数return True时才提交表单,return False时不提交表单。
(2)html文件:<form>中设置 action和method="post",<input> 中设置 name
(3)主py文件中:from flask import request, redirect, url_for;@app.route('/regist/', methods=['GET', 'POST’])
@app.route('/regist/',methods=['GET','POST']) def regist(): if request.method=='GET': return render_template('regist.html') else: usern=request.form.get('username') passw=request.form.get('password') nickn=request.form.get('nickname') user=User.query.filter(User.username==usern).first() if user: return u'username existed' else: user=User (username=usern,password=passw,nickname=nickn) db.session.add(user) db.session.commit() return redirect(url_for('login'))
3.实现登录
(1)js:设置return
(2)html:设置form;input;onclick="return fnLogin()"
(3)py:@app.route设置methods;GET;POST(读取表单数据查询数据库:用户名密码对:记住用户名,跳转到首页;用户名密码不对:提示相应错误。)
@app.route('/login/',methods=['GET','POST']) def login(): if request.method == 'GET': return render_template('login.html') else: usern = request.form.get('username') passw = request.form.get('password') user = User.query.filter(User.username == usern).first() if user: if user.check_password(passw): session['user'] = usern session['userid'] = user.id session.permanent = True return redirect(url_for('base')) else: return u'password error' else: return u'password is not existed'
4.python装饰器
@loginFirst#发布前登录,python装饰器 def loginFirst(func): @wraps(func) def wrapper(*args, ** kwargs): if session.get('user'): return func(*args, ** kwargs) else: return redirect(url_for('login')) return wrapper
5获取数据库
# 调用数据库把用户评论放在首页 @app.route('/index/') def index(): context = { 'questions':Question.query.all() } return render_template('index.html',**context)
6实现搜索功能
(1)准备视图函数search()
(2)修改base.html 中搜索输入框所在的
<form action="{{ url_for('search') }}" method="get">
<input name="q" type="text" placeholder="请输入关键字">
(3)完成视图函数search()
获取搜索关键字
q = request.args.get('q’)
条件查询
qu = Question.query.filter(Question.title.contains(q)).order_by('-creat_time’)
加载查询结果:
return render_template('index.html', question=qu)
组合条件查询
from sqlalchemy import or_, and_
7.密码保护
(1)更新User对象,设置对内的_password
class User(db.Model):
__tablename__ = 'user'
_password = db.Column(db.String(200), nullable=False) #内部使用
(2)编写对外的password
from werkzeug.security import generate_password_hash, check_password_hash
@property
def password(self): #外部使用,取值
return self._password
@password.setter
def password(self, row_password):#外部使用,赋值
self._password = generate_password_hash(row_password)
(3)密码验证的方法:
def check_password(self, row_password): #密码验证
result = check_password_hash(self._password,row_password)
return result
(4)登录验证:
password1 = request.form.get('password')
user = User.query.filter(User.username == username).first()
if user:
if user.check_password(password1):
8评论页的导航
(1)个人中心—视图函数带标签页面参数tag
@app.route('/usercenter/<user_id>/<tag>')
def usercenter(user_id, tag):
if tag == ‘1':
return render_template('usercenter1.html', **context)
(2)个人中心—导航标签链接增加tag参数
<li role=“presentation”><a href=“{{ url_for(‘usercenter’,user_id = user.id,tag = ‘1’) }}">全部问答</a></li>
(3)个人中心—有链接到个人中心页面的url增加tag参数
<a href="{{ url_for('usercenter',user_id = session.get('userid'), tag=1) }}">{{ session.get('user') }}</a>
#个人信息页 @app.route('/usercenter/<user_id>/<tag>') @loginFirst#发布前登录,python装饰器 def usercenter(user_id,tag): user=User.query.filter(User.id== user_id).first() context={ 'user':user } if tag=='1': return render_template('user1.html',**context) elif tag=='2': return render_template('user2.html',**context) else: return render_template('user3.html',**context)
四.Mysql数据库
1.models.py
from datetime import datetime from werkzeug.security import check_password_hash from werkzeug.security import generate_password_hash from exts import db #登录的数据库 class User(db.Model): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(20), nullable=False) #password = db.Column(db.String(20), nullable=False) _password = db.Column(db.String(200), nullable=False)#内部使用 nickname = db.Column(db.String(20)) @property def password(self):#外部使用 return self._password @password.setter def password(self,row_password): self._password=generate_password_hash(row_password) def check_password(self,row_password): result =check_password_hash(self._password,row_password) return result #db.create_all() #问题页的数据库 class Question(db.Model): __tablename__ = 'question' id = db.Column(db.Integer, primary_key=True, autoincrement=True) title = db.Column(db.String(100), nullable=False) detail = db.Column(db.Text, nullable=False) creat_time= db.Column(db.DateTime,default=datetime.now) author_id=db.Column(db.Integer,db.ForeignKey('user.id')) author=db.relationship('User',backref=db.backref('questions')) #db.create_all() class Comment(db.Model): __tablename__ = 'comment' id = db.Column(db.Integer, primary_key=True, autoincrement=True) author_id = db.Column(db.Integer, db.ForeignKey('user.id')) question_id=db.Column(db.Integer, db.ForeignKey('question.id')) detail = db.Column(db.Text, nullable=False) creat_time = db.Column(db.DateTime, default=datetime.now) question=db.relationship('Question',backref=db.backref('comments',order_by=creat_time.desc)) author = db.relationship('User', backref=db.backref('comments')) #db.create_all()
2.用户模型
config.py
import os SECRET_KEY = os.urandom(24) # SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:@127.0.0.1:3306/misdb1?charset=utf8' # SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@127.0.0.1:3306/misdb1?charset=utf8' SQLALCHEMY_TRACK_MODIFICATIONS = False