1.超文本标记语言,标准通用标记语言下的一个应用,在网站网址广泛应用。本学期我我学习了管理信息系统这门课程,对WEB网站前端后端有了一概念性的认识,并在老师的指导和同学的帮助下,利用Python+Flask+MysqL技术尝试搭建了自己的小网页,并在这个过程中学习了html语言,同时也更加清楚的认识到自己知识的浅薄,这门课程激发了自己对于网页设计的兴趣,使得对网页的理解不仅仅停留在使用的层次,而是解开了神秘面纱,认清了其实是人人能学并能学好的一门技术,在今后的学习中,会更加认真对待,实现更多的功能。这次制作的网页暂时只有登录注册,发布问答评论,个人中心的功能,期待今后实现更多。
2.界面与程序及数据库连接
import os
SECRET_KEY = os.urandom(24)
SQLALCHEMY_DATABASE_URI = ‘mysql+pymysql://root:123456@localhost:3306/mis_db?charset=utf8‘
SQLALCHEMY_TRACK_MODIFICATIONS = False
2.1.加载静态文件,父模板的继承和扩展
<!DOCTYPE HTML> <html> <meta charset="UTF-8"> <title>{% block title %}Base{% endblock %}</title> <link href="{{ url_for(‘static‘,filename=‘CSS/base.css‘) }}" rel="stylesheet" type="text/css"> <script src="{{ url_for(‘static‘,filename=‘JScript/base.js‘) }}"></script> {% block head %}{% endblock %} </head> <body id="mybody" background="../static/image/beijing.jpg"> <nav class="meue" > <div style="float: left;"> <img src=" {{ url_for(‘static‘,filename=‘image/smail.PNG‘) }}" weight="50" height="50"> </div> <div style="line-height:480%;"> <img id="on_off" src="{{ url_for(‘static‘,filename=‘image/on1.PNG‘) }}" onclick="MySwitch()" width="30px" > </div> <div > {% if username %} <a href="{{ url_for(‘usercenter1‘,user_id =session.get(‘id‘),tag=1) }}" style="font-weight: 600">{{ username }}</a> <a href="{{ url_for(‘logout‘) }}">登出</a> {% else %} <a href="{{ url_for(‘login‘) }}">登录</a> <a href="{{ url_for(‘regist‘) }}">注册</a> {% endif %} </div> <div style="line-height:340%;">|</div> <div class="search"> <form action="{{ url_for(‘search‘) }}" method="get"> <input name="q" type="text" name="search" style="width:300px;"> <button type="submit" ><img src="{{ url_for(‘static‘,filename=‘image/search.png‘) }}" width="14" height="14"></button> </form> </div> <div> <a href="{{ url_for(‘home‘) }}">首页</a> <a href="{{ url_for(‘question‘) }}">问答</a> <a href="http://photo.sina.com.cn/">图片</a> <a href="http://www.iqiyi.com/">视频</a> <a href="https://www.zhihu.com/explore">发现</a> </div> </nav> {% block main %}{% endblock %} <footer class="copyright"> <a>版权开发:lihaili</a> </footer> </body> </html>
2.2首页,登录界面,注册界面及其html,代码
{% extends ‘base.html‘ %} {% block title %}Home{% endblock %} {% block head %}#首页 <link href="{{ url_for(‘static‘,filename=‘CSS/home.css‘) }}" rel="stylesheet" type="text/css"> {% endblock %} {% block main %} <div align="center"> <ul> <img class="view" src="{{ url_for(‘static‘,filename=‘image/note.png‘) }}"> {% for foo in questions %} <li> <div class="content"> <div class="author"> <img src="{{ url_for(‘static‘,filename=‘image/boy.png‘) }}"> <a href="{{ url_for(‘usercenter1‘,user_id=foo.author_id,tag=1) }}">{{ foo.author.username }}</a> <span>{{ foo.creat_time }}</span> <p class="comp">[{{ foo.comments|length }}]</p> <img class="com" src="{{ url_for(‘static‘,filename=‘image/comment.png‘) }}"> </div> <br> <a class="title" href="{{ url_for(‘detail‘,question_id=foo.id) }}">{{ foo.title }}</a><br> <p>{{ foo.detail }}</p> </div> </li> {% endfor %} </ul> </div> {% endblock %}
{% extends ‘base.html‘ %} {% block title %}Login{% endblock %} {% block head %} <link href="{{ url_for(‘static‘,filename=‘CSS/login.css‘) }}" rel="stylesheet" type="text/css"> <script src="{{ url_for(‘static‘,filename=‘JScript/login.js‘) }}"></script> {% endblock %} {% block main %} <div class="login"> <form action="{{ url_for(‘login‘) }}" method="post"> <div class="login-top"> <h1>登录</h1> <input id="uname" name="username" type="text" value="Username" onfocus="this.value = ‘‘;" onblur="if (this.value==‘‘){ this.value = ‘Username‘;}"> <input id="upass" name="password" type="password" value="Password" onfocus="this.value = ‘‘;" onblur="if (this.value==‘‘){ this.value = ‘Password‘;}"> <div class="forgot"> <input type="checkbox"><p>记住账号</p> </div> </div> <div class="login-bottom"> <div id="errorbox"></div><button onclick="return MyLogin()" value="登录">Enter</button> </div> </form> </div> {% endblock %}
{% extends ‘base.html‘ %} {% block title %}Register{% endblock %} {% block head %} <link href="{{ url_for(‘static‘,filename=‘CSS/regist.css‘) }}" rel="stylesheet" type="text/css"> <script src="{{ url_for(‘static‘,filename=‘JScript/regist.js‘) }}"></script> {% endblock %} {% block main %} <div class="login"> <form action="{{ url_for(‘regist‘) }}" method="post"> <div class="login-top"> <h1>注册信息</h1> <input id="uname" name="username" type="text" value="Username" onfocus="this.value = ‘‘;" onblur="if (this.value==‘‘){ this.value = ‘Username‘;}"> <input id="fpass" name="password" type="password" value="Password" onfocus="this.value = ‘‘;" onblur="if (this.value==‘‘){ this.value = ‘Password‘;}"> <input id="spass" type="password" value="Password" onfocus="this.value = ‘‘;" onblur="if (this.value==‘‘){ this.value = ‘Password‘;}"> </div> <div class="login-bottom"> <div id="errorbox"></div><button onclick="return MyRegister()">注册</button> </div> </form> </div> {% endblock %}
2.3个人中心
{% extends ‘base.html‘ %} {% block title %}Center{% endblock %} {% block head %} <link href="{{ url_for(‘static‘,filename=‘CSS/center.css‘) }}" rel="stylesheet" type="text/css"> {% endblock %} {% block main %} <div class="center" > <h2><a href="{{ url_for(‘usercenter1‘,user_id=user.id,tag=1) }}"> {{ user.username }}</a></h2> <ul class="base"> <li role="presentation"><a href="{{ url_for(‘usercenter1‘,user_id=user.id,tag=‘1‘) }}">所有提问</a></li> <li role="presentation"><a href="{{ url_for(‘usercenter1‘,user_id=user.id,tag=‘2‘) }}">所有评论</a></li> <li role="presentation"><a href="{{ url_for(‘usercenter1‘,user_id=user.id,tag=‘3‘) }}">个人信息</a></li> </ul> {% block usercenter %}{% endblock %} </div> {% endblock %}
2.4发布问答,评论
{% extends ‘base.html‘ %} {% block title %}Question{% endblock %} {% block head %} <link href="{{ url_for(‘static‘,filename=‘CSS/question.css‘) }}" rel="stylesheet" type="text/css"> {% endblock %} {% block main %} <div class="question"> <h3>发布问答</h3> <form action="{{ url_for(‘question‘) }}" method="post"> <div > <br> <label for="ask" align="center">标题</label> <br> <input name="title" type="text" style="height: 22px;" id="questionTitle" placeholder="这里输入短标题"></input> </div> <br> <div> <label for="questionDetail" align="center">详情</label> <br> <textarea name="detail" rows="8" id="questionDetail" placeholder="说点什么吧....."></textarea> </div> <input type="checkbox"><p>同意《用户发布问答准则》</p> <br> <button type="submit" class="btn-default">发布</button> </form> </div> {% endblock %}
{% extends ‘base.html‘ %} {% block title %}Detail{% endblock %} {% block head %} <link href="{{ url_for(‘static‘,filename=‘CSS/detail.css‘) }}" rel="stylesheet" type="text/css"> {% endblock %} {% block main %} <div class="detail"> <h2>{{ question.title }}</h2> <a href="{{ url_for(‘usercenter1‘,user_id=question.author_id,tag=1) }}">{{ question.author.username }}</a> <span>{{ question.creat_time }}</span> <div class="p"> <p>{{ question.detail }}</p> </div> <form action="{{ url_for(‘comment‘) }}" method="post"> <textarea name="detail" rows="5"></textarea><br> <button >发送</button> <input name="question_id" type="hidden" value="{{ question.id }}"> </form> <br> <ul> <p style="font-weight: 600;font-size: 16.5px">评论[{{ question.comments|length }}]</p> <div> {% for foo in question.comments %} <li> <img src="{{ url_for(‘static‘,filename=‘image/xiaolian.png‘) }}"> <a href="{{ url_for(‘usercenter1‘,user_id=foo.author_id,tag=1) }}">{{ foo.author.username }}</a> <span>{{ foo.creat_time }}</span><br> <p>{{ foo.detail }}</p> </li> {% endfor %} </div> </ul> </div> {% endblock %}
3.主py代码
主PY文件写视图函数,带id参数。 首页标题的标签做带参数的链接,在详情页将数据的显示在恰当的位置。建立评论的对象关系映射,尝试实现发布评论。
from flask import Flask,render_template,request,redirect,url_for,session from flask_sqlalchemy import SQLAlchemy import config from functools import wraps from datetime import datetime from sqlalchemy import or_,and_ from werkzeug.security import generate_password_hash,check_password_hash app = Flask(__name__) app.config.from_object(config) db=SQLAlchemy(app) 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) #内部使用 @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) 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(‘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‘)) 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() @app.route(‘/‘) def home(): context={ ‘questions‘: Question.query.order_by(‘-creat_time‘).all() } return render_template(‘home.html‘,**context) @app.route(‘/detail/<question_id>‘) def detail(question_id): question=Question.query.filter(Question.id==question_id).first() return render_template(‘detail.html‘,question=question) # 登录装饰器 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(‘/comment/‘,methods=[‘POST‘]) @loginFirst def comment(): detail=request.form.get(‘detail‘) author_id = User.query.filter(User.username == session.get(‘user‘)).first().id question_id = request.form.get(‘question_id‘) comment = Comment(author_id=author_id,question_id=question_id,detail=detail) db.session.add(comment) # 保存到数据库 db.session.commit() # 提交 return redirect(url_for(‘detail‘,question_id=question_id)) @app.route(‘/usercenter/<user_id>/<tag>‘) @loginFirst def usercenter1(user_id,tag): user=User.query.filter(User.id==user_id).first() context={ ‘user‘:user } if tag==‘1‘: return render_template(‘userques.html‘,**context) elif tag==‘2‘: return render_template(‘usercom.html‘, **context) else: return render_template(‘userinfo.html‘, **context) # @app.route(‘/usercenter/<user_id>‘) # @loginFirst # def usercenter2(user_id): # user = User.query.filter(User.id == user_id).first() # context = { # ‘user‘: user # } # return render_template(‘center_two.html‘, **context) # 显示登录的用户名 @app.context_processor def mycontext(): usern=session.get(‘user‘) if usern: return {‘username‘:usern} else: return {} @app.route(‘/login/‘,methods=[‘GET‘,‘POST‘]) def login(): if request.method==‘GET‘: return render_template(‘login.html‘) else: username = request.form.get(‘username‘) password = request.form.get(‘password‘) user = User.query.filter(User.username==username).first() if user: if user.check_password(password): session[‘user‘] = username session[‘id‘] = user.id session.permanent = True return redirect(url_for(‘home‘)) else: return ‘Password error‘ else: return ‘Username inexistent‘ @app.route(‘/logout/‘) def logout(): session.clear() return redirect(url_for(‘login‘)) @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‘) user = User.query.filter(User.username == username).first() if user: return ‘Username existed‘ else: user1 = User(username=username, password=password) db.session.add(user1) db.session.commit() return redirect(url_for(‘login‘)) @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‘) user=User.query.filter(User.username == session.get(‘user‘)).first() author_id = user.id question = Question.query.filter(Question.title == title).first() if question: return ‘Question existed‘ else: question1 = Question(title=title, detail=detail, author_id=author_id) question1.author = user db.session.add(question1) # 保存到数据库 db.session.commit() # 提交 return redirect(url_for(‘home‘)) @app.route(‘/search/‘) @loginFirst def search(): que=request.args.get(‘q‘) ques=Question.query.filter( or_( Question.title.contains(que), Question.detail.contains(que), ) ).order_by(‘-creat_time‘) return render_template(‘home.html‘,questions=ques) if __name__ == ‘__main__‘: app.run(debug=True)
实现登录后更新导航:用上下文处理器app_context_processor定义函数,获取session中保存的值,返回字典。在父模板中更新导航,插入登录状态判断代码。注意用{% ... %}表示指令、{{ }}表示变量。完成注销功能:清除session并进行跳转页面。
编写要求登录的装饰器,定义函数将其返回。应用装饰器,要求在发布前进行登录,登录后可发布。建立发布内容的对象关系映射,完成发布函数。