期末作品检查
期末作品检查
完成内容:
- 网站父模板统一布局:头部导航条、底部图片导航、中间主显示区域布局
- 注册、登录、注销
- 发布、列表显示
- 详情页
- 评论、列表显示
- 个人中心
- 搜索,条件组合搜索
1.网站父模板统一布局:头部导航条、底部图片导航、中间主显示区域布局
- 用url_for加载静态文件
- <script src="{{ url_for('static',filename='js/login.js') }}"></script>
- flask 从static文件夹开始寻找
- 可用于加载css, js, image文件
- 继承和扩展
- 把一些公共的代码放在父模板中,避免每个模板写同样的内容。base.html
- 子模板继承父模板
- {% extends 'base.html’ %}
- 父模板提前定义好子模板可以实现一些自己需求的位置及名称。block
- <title>{% block title %}{% endblock %}-MIS问答平台</title>
- {% block head %}{% endblock %}
- {% block main %}{% endblock %}
- 子模板中写代码实现自己的需求。block
- {% block title %}登录{% endblock %}
- 首页、登录页、注册页都按上述步骤改写。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>fire</title> <link rel="stylesheet" type="text/css" href="../static/css/20.css"> <link rel="stylesheet" type="text/css" href="../static/css/200.css"> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous"> <script src="../static/js/39.js"></script> <style type="text/css"> a{ color: #000000; } body,div { padding: 0; margin: 0; } </style> </head> <body background="/static/timg.jpg" style="background-attachment: fixed;background-size: 100% 100%" > <h1 align="center"><span style="font-size:100px;color:lightskyblue">美丽の物</span></h1> <nav style="margin:0" align="center" > <a class="badge badge-primary" href={{ url_for('index') }}>INDEX</a> <form action="{{ url_for('search') }}" method="GET"> <div class="row"> <div class="col-lg-6 offset-lg-3"> <div class="input-group"> <input name="q" type="text" class="form-control touming" placeholder="Search" aria-label="Product name"> <span class="input-group-btn"> <button class="btn btn-primary " type="submit">Search</button> </span> </div> </div> </div></form> </span> {% if username %} <a href="{{ url_for('usercenter',user_id=session.get('userid'),tag=1) }}" class="badge badge-primary">{{ username }}</a> <a href="{{ url_for('logout') }}"class="badge badge-primary">logout</a> {% else %} <a href="{{ url_for('login') }}"class="badge badge-primary">LOGIN</a> <a href="{{ url_for('rege') }}"class="badge badge-primary">REGIST</a> {% endif %} <a class="badge badge-primary" href={{ url_for('question') }}>QUESTION</a> </nav> {% block question %}{% endblock %} {% block rege %}{% endblock %} {% block login %}{% endblock %} {% block index %}{% endblock %} {% block detail %}{% endblock %} {% block userbase %}{% endblock %} </body> </html>
{% extends 'basic.html' %} {% block title %}登陆{% endblock %} {% block index %} </head> <style> .nav_ul li { list-style: none; } </style> <body class="abc"> <h3 style="margin-left: 10%" >Comperhantion</h3> <div class="col-7" style="margin-left: 20%" > <div class="card touming " > <div class="card-body"> {% for foo in question %} <h4 class="card-title"><a href="{{ url_for('detail',question_id=foo.id) }}">{{ foo.title }}</a></h4> <h6 class="card-subtitle mb-2 text-muted"><a href="{{ url_for('usercenter',user_id=foo.author_id,tag=1) }}">{{ foo.author.username }}</a></h6> <p class="card-text">{{ foo.detail }}</p> <span class="card-text"style="float: right"><strong>发表时间:</strong>{{ foo.creat_time }}</span> <hr> {% endfor %} </div> </div> </div> {# </ul>#} <div> <div class="img"> <a href={{ url_for('login') }}> <img src="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=4071790924,2914289697&fm=27&gp=0.jpg"> </a> <div class="desc"><a href={{ url_for('login') }}>登陆</a></div> </div> <div class="img"> <a href={{ url_for('rege') }}> <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1508478993164&di=21005bc9d7cbc500390e5b62c3b859a7&imgtype=0&src=http%3A%2F%2Fwapfile.desktx.com%2Fpc%2F161122%2Fbigpic%2F5832b76c05a7e.jpg"> </a> <div class="desc"><a href={{ url_for('rege') }}>注册</a></div> </div> </div> <br> <div class="clearfloat"> <img src="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=4071790924,2914289697&fm=27&gp=0.jpg"> <img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1508478993164&di=21005bc9d7cbc500390e5b62c3b859a7&imgtype=0&src=http%3A%2F%2Fwapfile.desktx.com%2Fpc%2F161122%2Fbigpic%2F5832b76c05a7e.jpg"> </div> </body> </html>{% endblock %}
2 .注册、登录、注销
-
-
- js文件: onclick函数return True时才提交表单,return False时不提交表单。
- html文件:
- <form>中设置 action和method="post"
- <input> 中设置 name
- 主py文件中:
- from flask import request, redirect, url_for
- @app.route('/regist/', methods=['GET', 'POST’])
def regist():
if request.method == 'GET':
return render_template('regist.html')
else:
username = request.form.get(‘username’)#获取form中的数据
判断用户名是否存在:存在报错
不存在,存到数据库中
redirect重定向到登录页
username:<input id="uname" type="text"name="username"placeholder="username"><br> password:<input id="upass" type="password"name="password" placeholder="password"><br> <a href="https://image.baidu.com/">Forgot Password?</a> <div id="error_box"> <br></div> <button class="body" onclick="myLogin()" value="Log In"style="width: 250px;height: 50px;background-color: aqua;"> <div id="content" style=";height:150px;width:400px;float:left;"></div> <div class="touming" id="footer" style="background-color:aqua;clear:both;text-align:center;color: darkcyan;">版权 © djc</div>
@app.route('/') def index(): context = { 'question':Question.query.order_by('-creat_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') 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('index')) else: return u'password error' else: return u'password is not existed' @app.route('/rege/',methods=['GET','POST']) def rege(): if request.method =='GET': return render_template('rege.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 'username.existed.' else: user1 = User(username=usern,password=passw,nickname = nickn) db.session.add(user1) db.session.commit() return redirect(url_for('login')) def loginFrist(func): @wraps(func) def wrapper(*args, **kwargs): if session.get('user'): return func(*args, **kwargs) else: return redirect(url_for('login')) return wrapper
<h4 align="center"class="ads"> Management system</h4> <div style="margin:0" align="center"> <div id="container" style="width:400px " > <div class="touming" id="header" style="background-color: aqua;color: darkcyan;"><h2 align="center" style="margin-bottom:0;"> CREATE ACCOUNT</h2></div> <div align="center" > <input id="uname" type="text"name="username"placeholder="someone@example.com"><br> <input id="upass" type="password"name="password" placeholder="create password"><br> <input id="oupass" type="password"name="apassword" placeholder="again password"><br> <input id="unickname" type="text"name="nickname"placeholder="nickname"><br> <a href={{ url_for('login') }}>Log in </a> <div id="error_box"> <br></div> <button class="body" value="CREATE"style="width: 250px;height: 50px;background-color: aqua;">create</button> <div id="content" style=";height:150px;width:400px;float:left;"></div>
3发布、
-
- 编写要求登录的装饰器
from functools import wraps
def loginFirst(func): #参数是函数
@wraps(func)
def wrapper(*args, ** kwargs): #定义个函数将其返回
#要求登录
return func(*args, ** kwargs)
return wrapper #返回一个函数
- 应用装饰器,要求在发布前进行登录,登录后可发布。
@app.route('/question/',methods=['GET','POST'])
@loginFirst
def question():- 建立发布内容的对象关系映射。
class Question(db.Model):
- 完成发布函数。
保存到数据库。
重定向到首页。
-
@app.route('/question/', methods=['GET', 'POST']) @loginFrist 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'))
<form align="center" action="{{ url_for('question') }}" method="POST" > <h3 style="margin:0" align="center" >发布问答</h3> <form class="box" > <div class="form-group"style="margin:0" align="center" > <label for="ask">问题</label> <br> <textarea style="width: 15cm" class="form-control touming" rows="1" id="ask" name="title"></textarea> </div> <br> <div class="form-group"> <label for="questionDetail">详细内容</label> <br> <textarea style="width: 15cm" class="form-control box touming" rows="10" id="questionDetail" name="detail"></textarea> </div> <div class="checkbox"></div> <button type="submit" class="btn btn-light">发布</button> <button type="submit" class="btn btn-light">返回</button> </div>
4.详情页
- 定义评论的视图函数
@app.route('/comment/',methods=['POST'])
def comment():
读取前端页面数据,保存到数据库中 - 用<input type="hidden" 方法获取前端的"question_id"
- 显示评论次数
- 要求评论前登录
- 尝试实现详情页面下的评论列表显示
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'))
@app.route('/detail/<question_id>') def detail(question_id): context = { 'comments': Comment.query.all() } quest=Question.query.filter(Question.id ==question_id).first() return render_template('detail.html',ques=quest) @app.route('/comment/',methods=['POST']) @loginFrist 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))
<body> <div class="card touming ax" style="width: 20rem;" > <div class="card-body"> <h4 class="card-title" >{{ ques.title }}</h4> <h6 class="card-subtitle mb-2 text-muted">{{ ques.author.username }}</h6> <p class="card-text" class="font-weight-bold">{{ ques.detail }}</p> <a href="#" class="card-link">{{ ques.creat_time }}</a> </div> </div> <form action="{{ url_for('comment') }}" method="post"> <div class="ax" style="margin-left: 38%" > <textarea class="touming" style="height: 60px;width: 10cm" name="new_comment" rows="10" placeholder="请写下评论" ></textarea><br> <input name="question_id" type="hidden" value="{{ ques.id }}"/> <button type="submit" class="btn btn-light">提交评论</button> </div> </form> <h3>comment:({{ ques.comments|length }})</h3> <ul class="#"> {% for foo in ques.comments %} <div class="card touming"> <div class="card-body "> <li style="list-style: none;"> <span class="icon" aria-hidden="true"></span> <br> <a href="{{ url_for('usercenter',user_id=foo.author_id,tag=1) }}"style="float:left">{{ foo.author.username}}</a> <br> <h3> <a href="{{ url_for('detail',question_id=foo.id) }}">{{ foo.title }}</a></h3> <p>{{ foo.detail }}</p> <span class="#"style="float:right">{{ foo.creat_time}}</span> </li> </div> </div> {% endfor %} </ul>
5.个人中心
- 个人中心—视图函数带标签页面参数tag @app.route('/usercenter/<user_id>/<tag>') def usercenter(user_id, tag): if tag == ‘1': return render_template('usercenter1.html', **context)
- 个人中心—导航标签链接增加tag参数 <li role=“presentation”><a href=“{{ url_for(‘usercenter’,user_id = user.id,tag = ‘1’) }}">全部问答</a></li>
- 个人中心—有链接到个人中心页面的url增加tag参数 <a href="{{ url_for('usercenter',user_id = session.get('userid'), tag=1) }}">{{ session.get('user') }}</a>
- 新页面userbase.html,用<ul ><li role="presentation"> 实现标签页导航。
<ul class="nav nav-tabs">
<li role="presentation"><a href="#">Home</a></li>
<li role="presentation"><a href="#">Profile</a></li>
<li role="presentation"><a href="#">Messages</a></li>
</ul> - 让userbase.html继承base.html。
重写title,head,main块.
将上述<ul>的样式放在head块,<ul>放在main块中.
定义新的块user。 - 让上次作业完成的个人中心页面,继承userbase.html,原个人中心就自动有了标签页导航。
- 制作个人中心的三个子页面,重写userbase.html中定义的user块,分别用于显示问答、评论、个人信息。
- 思考 如何实现点标签页导航到达不同的个人中心子页面。
{% extends 'basic.html' %} {% block title %}个人中心{% endblock %} {% block head %} <link rel="stylesheet" type="text/css" href="../static/css/20.css"> <link rel="stylesheet" type="text/css" href="../static/css/200.css"> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous"> <script src="../static/js/39.js"></script> <style type="text/css"> a{ color: #000000; } </style> {% endblock %} <body background="../static/timg.jpg" style="background-attachment: fixed;background-size: 100% 100%" > {% block userbase %} <div style="width:50rem; margin:0 auto"> <ul class="list-group list-group-flush"> <h2 style="margin: 0%;align:center">{{ user.username }}</h2> </ul> <li role="presentation"><a href="{{ url_for('usercenter',user_id=user.id,tag=1) }}">Question</a> </li> <li role="presentation"><a href="{{ url_for('usercenter',user_id=user.id,tag=2) }}">Comment</a> </li> <li role="presentation"><a href="{{ url_for('usercenter',user_id=user.id,tag=3) }}">Info</a> </li> </ul> </div> {% block main %}{% endblock %} {% endblock %} </body>
{% extends 'userbase.html' %} {% block title %}PERSONAL{% endblock %} {% block main %} <div class="touming"> <div class="card" style="width:50rem; margin:0 auto"> <ul class="list-group list-group-flush"> <h3 style="margin:0" align="center">ANSWER</h3> {% for foo in user.questions %} <li class="list-group-item"> <span class="icon" aria-hidden="true"></span> <br> <h3> <a href="{{ url_for('detail',question_id=foo.id) }}">{{ foo.title }}</a></h3> <p>{{ foo.detail }}</p> <span class="badge"style="float:right">{{ foo.creat_time}}</span> <a href="{{ url_for('usercenter',user_id=foo.author.id) }}">{{ foo.author.username}}</a> </li> {% endfor %} </ul> </div> </div> {% endblock %}
{% extends 'userbase.html' %} {% block title %}PERSONAL{% endblock %} {% block main %} <div class="card touming" style="width:50rem; margin:0 auto"> <ul class="list-group list-group-flush"> <h3 style="margin:0" align="center">COMMENT</h3> {% for foo in user.comments %} <li class="list-group-item"> <span class="icon" aria-hidden="true"></span> <br> <h3> <a href="{{ url_for('detail',question_id=foo.id) }}">{{ foo.title }}</a></h3> <p>{{ foo.detail }}</p> <span class="badge"style="float:right">{{ foo.creat_time}}</span> <a href="#">{{ foo.author.username}}</a> </li> {% endfor %} </ul> </div> {% endblock %}
{% extends 'userbase.html' %} {% block title %}PERSONAL{% endblock %} {% block main %} <body class="abc"> <div class="card touming" style="width:50rem; margin:0 auto"> <h3 style="margin:0" align="center" color="blue">{{ username }}MESSAGE</h3> <ul class="list-group list-group-flush"> <li class="list-group-item"> <span class="icon" aria-hidden="true"> Username:{{ user.username }}<br> id:{{ user.id }}<br> nickname:{{ user.nickname }}<br> Comperhantion:{{ user.questions|length }} </span> </li> </ul> </div> </body> {% endblock %}
@app.route('/usercenter/<user_id>/<tag>') @loginFrist def usercenter(user_id,tag): user=User.query.filter(User.id==user_id).first() context={ # 'username':user.username, # 'question':user.questions, # 'comments':user.comment 'user':user } 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)
5.搜索,条件组合搜索
@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('-creat_time') return render_template('index.html',question = ques)
现搜索功能
- 修改base.html 中搜索输入框所在的
- <form action="{{ url_for('search') }}" method="get">
- <input name="q" type="text" placeholder="请输入关键字">
- 完成视图函数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_
示例:
Lobby.query.filter(
or_(
and_(
Lobby.id == Team.lobby_id,
LobbyPlayer.team_id == Team.id,
LobbyPlayer.player_id == player.steamid
),
and_(
Lobby.id == spectator_table.c.lobby_id,
spectator_table.c.player_id == player.steamid
)
)<form action="{{ url_for('search') }}" method="GET"> <div class="row"> <div class="col-lg-6 offset-lg-3"> <div class="input-group"> <input name="q" type="text" class="form-control touming" placeholder="搜索" aria-label="Product name"> <span class="input-group-btn"> <button class="btn btn-primary " type="submit">Search</button> </span> </div> </div> </div></form>
- 新页面userbase.html,用<ul ><li role="presentation"> 实现标签页导航。
- 定义评论的视图函数