期末作品检查
- 期末作品检查:基本要求
- 检查时间:18最后四节课,上课之前必须全部完成,上课做基本部署就开始检查
- 方式:逐个运行演示,抽查代码
- 主题:选一个主题,整个网站风格统一,布局合理,尽量美观。
- 期末作品检查:必须完成:
- 网站父模板统一布局:头部导航条、底部图片导航、中间主显示区域布局
- 注册、登录、注销
- 发布、列表显示
- 详情页
- 评论、列表显示
- 个人中心
- 搜索,条件组合搜索
- 一篇完整的博客
- 个人学期总结
- 总结Python+Flask+MysqL的web建设技术过程,标准如下:
- 即是对自己所学知识的梳理
- 也可作为初学入门者的简单教程
- 也可作为自己以后复习的向导
- 也是一种向外展示能力的途径
- 期末作品检查:加分功能
- 文章分类、显示
- 点赞、收藏
- 修改密码、头像、上传头像
- 我的
- 高级搜索
- 个人学期总结
经过一个学期的学习,在老师的教导之下,从一个连网页制作都不会的菜鸟,变成会用Python+Flask+MysqL的web建设技术来制作网页。
一开始是学习简单输入输出交互,算并输出两个数字之和,输入半径,计算圆的面积。到画圆,太阳花,同心圆画五角星,字符串基础操作,恺撒密码的编码,打出99乘法表,英文词频统计,用文件方式实现完整的英文词频统计,中文词频统计,datetime处理日期和时间,timestamp与timedelta,这些都是比较简单的,比较容易上手,逐渐的,web的基础,用html元素制作web网页,导航,css基础,图片导航块,到登录,登录和注册页面的前端验证再到连接myssql数据库,创建用户模型,对数据库进行增删改查操作,完成注册功能,登录后更新导航,发布功能,制作首页的显示列表,显示全部问答,完成问答详情页的布局,点击问答标题时跳转到相应的详情页,评论功能的实现,个人中心的显示,个人中心标签导航,搜索功能的实现,密码的保护等等。在学习的过程中发现了很多乐趣。
Python+Flask+MysqL的web建设技术过程
主py文件:
from functools import wraps from flask import Flask, render_template, url_for, redirect, request, session import config from sqlalchemy import or_,and_ from exts import db from models import User,Question,Comment app = Flask(__name__) app.config.from_object(config) db.init_app(app) # db.create_all() # 增加 # user = User(username='tan1997',password='19961021') # db.session.add(user) # db.session.commit() # 查询 # user = User.query.filter(User.username == 'tan1997').first() # print(user.username,user.password) # 修改 # user=User.query.filter(User.username == 'tan1997').first() # user.password=1234567 # db.session.commit() # 删除 # user=User.query.filter(User.username == 'tan1997').first() # db.session.delete(user) # db.session.commit() @app.route('/') def index(): context = { 'question': Question.query.order_by('-create_time').all() } return render_template("index.html", **context) @app.route('/login/', methods=['GET', 'POST']) def login(): if request.method == 'GET': return render_template("login.html") else: usern = request.form.get('username') password1 = request.form.get('password') user = User.query.filter(User.username == usern).first() if user: if user.check_password(password1): session['user'] = usern session['id'] = user.id session.permanent = True return redirect(url_for('index')) else: return '密码错误' else: return '用户名不存在' @app.context_processor def mycontext(): usern = session.get('user') if usern: return { 'susername': usern, } else: return {} 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 # 返回一个函数 @app.route('/regist/', methods=['GET', 'POST']) def regist(): if request.method == 'GET': return render_template("regist.html") else: username = request.form.get('username') password = request.form.get('password') nickname = request.form.get('nickname') user = User.query.filter(User.username == username).first() if user: return ' 用户名已存在' else: user = User(username=username, password=password, nickname=nickname) db.session.add(user) # 数据库,添加操作 db.session.commit() return redirect(url_for('login')) @app.route('/logout/') def logout(): session.clear() return redirect(url_for('index')) @app.route('/question/', methods=['GET', 'POST']) @loginFirst # 使用定义的装饰器 def question(): if request.method == 'GET': return render_template('question.html') else: title = request.form.get('title') detail = request.form.get('detail') author_id = User.query.filter(User.username == session.get('user')).first().id question = Question(title=title, detail=detail, author_id=author_id) db.session.add(question) db.session.commit() # 事务提交,将数据添加进数据库 return redirect(url_for('index')) @app.route('/detail/<question_id>') # 和idea的update一样,将id带到控制器 def detail(question_id): quest = Question.query.filter(Question.id == question_id).first() # 根据id查询出整条元组记录,丢进quest return render_template('detail.html', ques=quest) # 把值quest丢进键quest,在detail.html页面调用 @app.route('/comment/', methods=['POST']) @loginFirst def comment(): comment = request.form.get('new_comment') ques_id = request.form.get('question_id') auth_id = User.query.filter(User.username == session.get('user')).first().id comm = Comment(author_id=auth_id, question_id=ques_id, detail=comment) db.session.add(comm) db.session.commit() return redirect(url_for('detail', question_id=ques_id)) @app.route('/user/<user_id>/<tag>') @loginFirst def user(user_id, tag): user = User.query.filter(User.id == user_id).first() context = { 'user': user, 'username': user.username, 'questions': user.question, # 用反向定义的question 'comments': user.comments } if tag == '1': return render_template('usercenter1.html', **context) elif tag == '2': return render_template('usercenter2.html', **context) else: return render_template('usercenter3.html', **context) # # @app.route('/usercenter1/<user_id>') # def usercenter1(user_id): # user = User.query.filter(User.id == user_id).first() # context = { # 'username_id': user.id, # 'username': user.username, # 'questions': user.question, # 用反向定义的question # 'comments': user.comments # } # return render_template('usercenter1.html', **context) # # # @app.route('/usercenter2/<user_id>') # def usercenter2(user_id): # user = User.query.filter(User.id == user_id).first() # context = { # 'username_id': user.id, # 'username': user.username, # 'questions': user.question, # 用反向定义的question # 'comments': user.comments # } # # return render_template('usercenter2.html', **context) # # # @app.route('/usercenter3/<user_id>') # def usercenter3(user_id): # user = User.query.filter(User.id == user_id).first() # context = { # 'username_id': user.id, # 'username': user.username, # 'questions': user.question, # 用反向定义的question # 'comments': user.comments # } @app.route('/search/') def search(): qu = request.args.get('q') ques = Question.query.filter\ (or_(Question.title.contains(qu), Question.detail.contains(qu) ) ).order_by('-create_time') return render_template('index.html',question=ques) if __name__ == '__main__': app.run(debug=True)
models.py文件:
from datetime import datetime from werkzeug.security import generate_password_hash,check_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(200), nullable=False) nickname = db.Column(db.String(50)) @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 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) create_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('question')) # 反向定义一个question 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')) create_time = db.Column(db.DateTime, default=datetime.now) detail = db.Column(db.Text, nullable=False) question = db.relationship('Question', backref=db.backref('comments', order_by=create_time.desc)) author = db.relationship('User', backref=db.backref('comments'))
exit.py文件:
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
manage.py文件:
from flask_script import Manager from flask_migrate import Migrate,MigrateCommand from myqa import app from exts import db from models import User,Question,Comment manager = Manager(app) # Manager只有一个参数:一个Flask实例 migrate = Migrate(app,db) # 使用Migrate绑定app和db # 添加迁移脚本命令 manager.add_command('db',MigrateCommand) # 加入命令,命令行输入python manage.py db migrate if __name__ == '__main__': manager.run()
config.py文件:
import os DEBUG = True SECRET_KEY = os.urandom(24) DIALECT = 'mysql' DRIVER = 'mysqldb' USERNAME = 'root' PASSWORD = 'ROOT' HOST = '127.0.0.1' DATABASE = 'mytest' SQLALCHEMY_DATABASE_URI='mysql+pymysql://root:@localhost:3306/mis_db?charset=utf8' SQLALCHEMY_TRACK_MODIFICATIONS = False
父模板html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>主页 {% block logintitle %} {% endblock %} {% block registtitle %} {% endblock %} {% block questiontitle %} {% endblock %} {% block indextitle %} {% endblock %} {% block detailtitle %} {% endblock %} {% block selfinfotitle %} {% endblock %} {% block usertitle %} {% endblock %} </title> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/myweb.css') }}"> <script src="{{ url_for('static',filename='js/switch.js') }}"></script> <script src="{{ url_for('static',filename='js/footerPosition.js') }}"></script> {% block loginhead %} {% endblock %} {% block registhead %} {% endblock %} {% block questionhead %} {% endblock %} {% block indexhead %} {% endblock %} {% block detailhead %} {% endblock %} {% block selfinfohead %} {% endblock %} {% block userhead %} {% endblock %} </head> <body id="myBody" style="background-image: url(/static/img/bg.jpg)"> <main> <nav class="navbar navbar-default" role="navigation"> <div class="container-fluid"> <div class="navbar-header"> <a href="{{ url_for('index') }}" class="navbar-brand">首页</a> <button type="submit" class="btn btn-default" style="margin-top: 12px"> <a href="{{ url_for('question') }}">发布</a></button> <form class="navbar-form navbar-left" action="{{ url_for('search') }}" method="get"> <div class="form-group"> <input name="q" type="text" class="form-control" placeholder="请输入关键字"> </div> <button type="submit" class="btn btn-default" style="margin-top: 3px">搜索</button> </form> </div> <ul class="nav navbar-nav navbar-right"> {% if susername %} <li><a href="{{ url_for('user',user_id =session.get('id'),tag = 1) }}">{{ susername }}</a></li> <li><a href="{{ url_for('logout') }}">注销</a></li> {% else %} <li><a href="{{ url_for('regist') }}"><span class="glyphicon glyphicon-user"></span> 注册</a></li> <li><a href="{{ url_for('login') }}"><span class="glyphicon glyphicon-log-in"></span> 登录</a> </li> {% endif %} <li style="float: right"><img id="myOnOff" onclick="mySwitch()" src="http://www.runoob.com/images/pic_bulbon.gif" class="bulb"></li> </ul> </div> </nav> </main> <footer class="fixed-bottom">@版权所有</footer> </body> {% block loginbody %} {% endblock %}. {% block registbody %} {% endblock %} {% block questiontbody %} {% endblock %} {% block indexbody %} {% endblock %} {% block detailbody %} {% endblock %} {% block selfinfobody %} {% endblock %} {% block userbody %} {% endblock %} </html>
首页html:
{% extends'myweb.html' %} {% block indextitle %}首页{% endblock %} {% block indexhead %} <link rel="stylesheet" type="text/css" href="../static/css/component.css"/> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <script src="../static/js/login.js"></script> {% endblock %} {% block indexbody %} <div class="container"> <div class="row clearfix"> <div class="col-md-10 column" id="rgba1"> <h3 align="center">旅游问答区域</h3> <ul> {% for foo in question %} <li> <a href="{{ url_for('user',user_id = foo.author_id,tag = 1) }}">{{ foo.author.username }}</a> <br> <p>标题:<a href="{{ url_for('detail',question_id=foo.id) }}">{{ foo.title }}</a></p> <br> <p>内容:{{ foo.detail }}</p> <span>评论数: ({{ foo.comments|length }})</span> <span class="badge pull-right">{{ foo.create_time }}</span> <hr> </li> {% endfor %} </ul> </div> </div> </div> {% endblock %}
登录页面html:
{% extends'myweb.html' %} {% block logintitle %}登录页面{% endblock %} {% block loginhead %} <link rel="stylesheet" type="text/css" href="../static/css/component.css"/> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <script src="../static/js/login.js"></script> {% endblock %} {% block loginbody %} <div class="logo_box"> <h3 class="h3">请登录</h3> <form action="{{ url_for('login') }}" method="post"> <div class="input_outer"> <span class="u_user"></span> <input id="uname" class="text" style="color: gold" type="text" placeholder="请输入账号" name="username"> </div> <div class="input_outer"> <span class="us_uer"></span> <input id="upass" class="text" style="color:black ; position:absolute; z-index:100;" value="" type="password" placeholder="请输入密码" name="password"> </div> <div class="errorText" id="error_box" style="color: black"><br></div> <div> <button onclick="return fnLogin()" class="lb1" style="color:black">登录</button> </div> </form> </div> {% endblock %}
注册页面html:
{% extends'myweb.html' %} {% block registtitle %}注册页面{% endblock %} {% block registhead %} <link rel="stylesheet" type="text/css" href="../static/css/component.css"/> <script src="../static/js/regist.js"></script> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> {% endblock %} {% block registbody %} <div class="logo_box"> <h3 class="h3">欢迎注册</h3> <form action="{{ url_for('regist') }}" method="post"> <div class="input_outer"> <span class="u_user"></span> <input id="uname" class="text" style="color: gold" type="text" placeholder="请输入账号" name="username"> </div> <div class="input_outer"> <span class="u_user"></span> <input id="unickname" class="text" style="color: black" type="text" placeholder="请输入昵称" name="nickname"> </div> <div class="input_outer"> <span class="us_uer"></span> <input id="upass" class="text" style="color:black ; position:absolute; z-index:100;" value="" type="password" placeholder="请输入密码" name="password"> </div> <div class="input_outer"> <span class="us_uer"></span> <input id="upass1" class="text" style="color:black ; position:absolute; z-index:100;" value="" type="password" placeholder="请再次输入密码"> </div> <div class="errorText" id="error_box" style="color: red"><br></div> <div> <button class="lb1" style="color:black" type="submit" onclick="return fnRegist()">注册</button> </div> </form> </div> {% endblock %}
发布问答页面html:
{% extends'myweb.html' %} {% block questiontitle %}问答页面{% endblock %} {% block questionhead %} <link rel="stylesheet" type="text/css" href="../static/css/myweb.css"/> <link rel="stylesheet" type="text/css" href="../static/css/component.css"/> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> {% endblock %} {% block questiontbody %} <h3 class="h3">发布问答</h3> <div class="ques"> <form action="{{ url_for('question') }}" method="post"> <div class="form-group"> <label for="questionTitle" style="color: black">标题</label><br> <textarea class="textareabg" rows="1" id="questionTitle" name="title" style="width: 700px"></textarea> <label for="questionDatail" style="color: black">详情:</label><br> <textarea class="textareabg" rows="5" id="questionDatail" name="detail" style="width: 700px"></textarea> <br> <div id=""><br></div> <input type="submit" value="发布" class="btn btn-default" onclick="" style="margin-left: 100%"> </div> </form> </div> {% endblock %}
问答详情页html:
{% extends 'myweb.html' %} {% block detailtitle %}问答详情{% endblock %} {% block detailhead %} <link rel="stylesheet" type="text/css" href="../static/css/component.css"/> <script src="../static/js/regist.js"></script> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> {% endblock %} {% block detailbody %} <div class="col-md-2 column "></div> <div class="col-md-8 column " id="rgba1"> <ul class="list-unstyled"> <li> <h2 href="#" class="text-center">{{ ques.title }}</h2> <br> <p class="text-center"> <a href="{{ url_for('user',user_id = session.get('id'),tag = 1) }}"> <small>{{ ques.author.username }}</small></a> </a>    <span class="pull-center"><small>{{ ques.create_time }}</small></span> </p> <p>{{ ques.detail }}</p> <form action="{{ url_for('comment') }}" method="post"> <div class="form-group"> <textarea name="new_comment" class="form-control" rows="5" id="comment" placeholder="请输入评论"></textarea> <input type="hidden" name="question_id" value="{{ ques.id }}"> </div> <button type="submit" class="btn btn-default" style="margin-left:48% ">发送</button> </form> </li> </ul> <hr> <h4>评论:({{ ques.comments|length }})</h4> <ul class="list-unstyled"> {% for foo in ques.comments %} <li class="list-group-item"> <a href="{{ url_for('user',user_id = foo.author.id,tag = 1) }}">{{ foo.author.username }}</a> <span class="badge pull-right">{{ foo.create_time }}</span> <p>{{ foo.detail }}</p> <br> </li> {% endfor %} </ul> </div> <div class="col-md-2 column "></div> {% endblock %}
个人中心html:
{% extends'myweb.html' %} {% block usertitle %}个人中心{% endblock %} {% block userhead %} {% endblock %} {% block userbody %} <div class="container"> <div class="row clearfix"> <div class="col-md-2 column"> </div> <div class="col-md-8 column"> <ul class="nav nav-tabs"> <li> <a href="{{ url_for('user',user_id = user.id,tag = 1) }}">全部问答</a> </li> <li> <a href="{{ url_for('user',user_id = user.id,tag = 2) }}">全部评论</a> </li> <li> <a href="{{ url_for('user',user_id = user.id,tag = 3) }}">个人信息</a> </li> </ul> </div> <div class="col-md-2 column"> </div> </div> </div> {% block user %}{% endblock %} {% endblock %}
{% extends 'user.html' %} {% block user %} <div class="container"> <div class="row clearfix"> <div class="col-md-2 column"> </div> <div class="col-md-8 column" id="rgba1"> <p class="text-center"> <small>{{ username }}</small> </p> <hr> <h3 align="center"> <small>全部问答</small> </h3> <ul class="list-unstyled"> {% for foo in questions %} <li class="list-group-item"> <span class="glyphicon glyphicon-user"></span><a>{{ foo.author.username }}</a> <p>标题:{{ foo.title }}</p> <p>问答内容:{{ foo.detail }}</p> <span class="badge pull-right">{{ foo.create_time }}</span><br> <br> </li> {% endfor %} </ul> </div> <div class="col-md-2 column"> </div> </div> </div> {% endblock %}
{% extends 'user.html' %} {% block user %} <div class="container"> <div class="row clearfix"> <div class="col-md-2 column"> </div> <div class="col-md-8 column" id="rgba1"> <p class="text-center"><small>{{ username }}</small></p> <hr> <h3 align="center"> <small>全部评论</small> </h3> <ul class="list-unstyled"> {% for foo in comments %} <li class="list-group-item"> <span class="badge pull-right">{{ foo.create_time }}</span> <p>文章标题:{{ foo.question.title }}</p> <p>评论内容:{{ foo.detail }}</p> <span class="glyphicon glyphicon-user"></span><small ><a>{{ foo.author.username }}</a></small> <br> </li> {% endfor %} </ul> </div> <div class="col-md-2 column"> </div> </div> </div> {% endblock %}
{% extends 'user.html' %} {% block user %} <div class="container"> <div class="row clearfix"> <div class="col-md-2 column"> </div> <div class="col-md-8 column" id="rgba1"> <p class="text-center"> <small>{{ username }}</small> </p> <hr> <h3 align="center"> <small>个人信息</small> </h3> <ul class="list-group"> <li class="list-group-item" style="background-color: antiquewhite"><span class="glyphicon glyphicon-user"></span>用户:{{ username }}</li> <li class="list-group-item" style="background-color: wheat">昵称</li> <li class="list-group-item" style="background-color: aquamarine">文章篇数:{{ questions|length }}</li> </ul> </div> <div class="col-md-2 column"> </div> </div> </div> {% endblock %