一、项目选择
- 继续沿用Python+Flask+MysqL的web建设技术,开发一个网站
- 网站主题根据个人兴趣与特长自由选择
- 此项目属于个人项目,每个同学独立完成,和其他同学不一样
二、项目要求
- 整个网站风格统一,布局合理,尽量美观。
- 作品必须完成:
- 网站父模板统一布局:头部导航条、底部图片导航、中间主显示区域布局
- 注册、登录、注销
- 发布、列表显示
- 详情页
- 评论、列表显示
- 个人中心
- 搜索,条件组合搜索
- 文章分类、显示
- 点赞、收藏
- 修改密码、头像、上传头像
- 我的发布、点赞、收藏、评论
- 高级搜索
- 热门文章、推荐文章
- 参考网站:http://bbs.xiaomi.cn/
三、提交材料
- 整个python项目文件夹
- 一项目文档,包括:
- 系统概要说明
- 网站结构设计
- 模块详细设计
- 数据库设计
- 系统实现的关键算法与数据结构
- 成品展示
四、材料提交方式及日期
-
- 每人提交一个文件夹,以学号姓名命名
- 个人文件夹里包含三述的材料:
- 整个python项目文件夹
- 一项目文档
- 请在2018/06/16 日期之前提交给学委
- 学委收齐后,整理刻录一张光盘交给老师。
- 空白光盘可找老师领取
- 建一个班级文件夹,里面放一个一个同学的文件夹,都不要压缩
1、系统概要说明
本篇文章主要是讲关于用数据库能够进行用户的注册,登录以及能增加用户的问答,评论功能,还有就是收藏和点赞功能,和在首页能显示不同用户发布的问答,有条件的查询以及热搜榜。
2、 网站结构设计
在根目录下有静态文件夹(static),html存放的文件夹(templates)以及主python文件以及config配置文件。static中又分别有三个文件夹,css,js和upload文件。css文件是用来布局美化的功能; js文件则是用来完成一些页面的特效功能; uploads文件就是用来 储存用户的头像图片。在templates中存放了所有页面的HTML,包含模板以及其余的html页面。
3、模块详细设计
- 客户端—首页遍历问答请求—查询数据库—返回所有问答
- 客户端--注册请求—查询数据库—返回页面(提示成功)—跳转登录页面
- 客户端—登录请求—查询数据库(有该用户)—返回页面(提示成功)—跳转首页
- 客户端—登录请求—查询数据库(查询不到该用户)—返回页面(提示登录不成功)—跳转到登录页面(重新登录)
- 客户端—问答评论请求—将评论的内容存入数据库—返回评论用户以及评论内容
- 客户端—点赞收藏请求—存入数据库—将加一后的数据返回页面
- 客户端—用户头像上传请求—存入用户表—返回用户图像
- 客户端—发布问答请求—存取数据到数据库—返回页面—跳转到首页
- 客户端—个人信息请求—查询数据库—返回从数据库查询到的个人信息
4、数据库设计
本系统运行的数据库要把格式转换为utf-8格式,不然发布问答的内容,标题不能输入文字,会显示错误,只能输入数字数据库里需要有五张表, user(用户)表,question(问答)表,comment(评论)表,collection(收藏)表以及cf(分类)表。
User表有用户ID,用户名,密码,icon,而密码是经过加密处理的。
Question表:问答id,title,detail,creat_time,用户id,类别,浏览次数和点赞次数。
Comment表:评论id,用户id,问答id,creat_time,detail。
Collection表:收藏id,问答id,用户id。
cf表:分类id,类别名。
5、系统实现的关键算法与数据结构
关键算法有注册,登录,发布问答和发布评论,个人信息
注册部分的代码:
@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 'error:user exitst'
else:
user = User(username=username, password=password)
db.session.add(user) # 加入数据库
db.session.commit()
return redirect(url_for('login'))
{% extends 'base.html' %}
{% block title %}
注册
{% endblock %}
{% block link %}
{% endblock %}
{% block box %}
<div class="container" style="padding-top: 100px;">
<script type="text/javascript" src="../static/js/ma.js"></script>
<div class="row clearfix">
<div class="col-md-8 column">
<form class="form-horizontal" role="form" method="post" action="{{ url_for('regist') }}">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label" style="color:blue">账号</label>
<div class="col-sm-10">
<input type="text" name="username" class="form-control" id="inputEmail3" required/>
</div>
</div>
<div class="form-group">
<label for="Password1" class="col-sm-2 control-label" style="color:blue">密码</label>
<div class="col-sm-10">
<input type="password" name="password" class="form-control" id="Password1" required/>
</div>
</div>
<div class="form-group">
<label for="Password2" class="col-sm-2 control-label" style="color:blue">确认密码</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="Password2"required/>
</div>
<br />
<br />
<br />
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" οnclick="return aaa()" class="btn btn-default" style="width:100%;background:pink;">注册</button>
</div>
</div>
</form>
</div>
<div class="col-md-4 column">
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script>
function aaa() {
var p1 = document.getElementById('Password1')
var p2 = document.getElementById('Password2')
if (p1.value != p2.value){
alert('两次密码不一样!')
return false;
}
return true;
}
</script>
{% endblock %}
代码解析:定义regist方法,获取get方法,打开注册页的模板,收到用户上传的信息,传送到数据库,匹配有没有相同的用户名,有的返回到注册页面并显示该用户名已存在。没有的就返回到登录页面进行登录。在注册的时候也会匹配两次输入的密码是否一致,不一致就会显示“两次密码不一致”,重新输入密码。
登录部分的代码:
# 登陆
@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['username'] = user.username
session['user_id'] = user.id
session.permanent = True
# 重新定位到首页
return redirect(url_for('index'))
else:
# 重新定位到注册
return redirect(url_for('login'))
else:
return redirect(url_for('login'))
{% extends 'base.html' %}
{% block title %}
登录
{% endblock %}
{% block link %}
{% endblock %}
{% block box %}
<div class="container" style="padding-top: 100px;">
<script type="text/javascript" src="../static/js/login.js"></script>
<div class="row clearfix">
<div class="col-md-8 column">
<form class="form-horizontal" role="form" method="post" action="{{ url_for('login') }}">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label" style="color:blue;">账号</label>
<div class="col-sm-10">
<input type="text" name="username" class="form-control" id="inputEmail3"/>
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label" style="color:blue;">密码</label>
<div class="col-sm-10">
<input type="password" name="password" class="form-control" id="inputPassword3"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox"/>Remember me</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">登录</button>
</div>
</div>
</form>
</div>
<div class="col-md-4 column">
</div>
</div>
</div>
{% endblock %}
{% block script %}
{% endblock %}
代码解析:定义login方法,请求方式是“get”,返回到'login.html'页面,获取数据,传送到数据库,匹配用户名和密码,如果匹配成功返回到首页,不成功返回到注册页面,进行注册。
发布问答部分的代码:
@app.route('/question', methods=['GET', 'POST'])
@loginFirst
def question():
if request.method == 'GET':
cf = Cf.query.all()
return render_template('question.html', cf=cf)
else:
title = request.form.get('title')
detail = request.form.get('detail')
author_id = request.form.get('author_id')
cf = request.form.get('cf')
question = Question(title=title, detail=detail, author_id=author_id, cf=cf)
db.session.add(question) # 加入数据库
db.session.commit()
return redirect(url_for('index'))
{% extends 'base.html' %}
{% block title %}
发布问答
{% endblock %}
{% block link %}
{% endblock %}
{% block box %}
<div class="container" style="padding-top: 100px;">
<div class="row clearfix">
<div class="col-md-8 column">
<form class="form-horizontal" role="form" method="post" action="#">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label"><span style="color:yellow">标题</span></label>
<div class="col-sm-10">
<input type="text" name="author_id" value="{{ user.id }}" hidden>
<input type="text" class="form-control" id="title" name="title"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="name"><span style="color:yellow">内容</span></label>
<div class="col-sm-10">
<textarea class="form-control" name="detail" rows="10"></textarea>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<select name="cf" id="" class="form-control">
<option value="">--请选择分类--</option>
{% for c in cf %}
<option value="{{ c.id }}">{{ c.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">发布</button>
</div>
</div>
</form>
</div>
<div class="col-md-4 column">
</div>
</div>
</div>
{% endblock %}
{% block script %}
{% endblock %}
代码解析:定义question方法,如果请求的方式是“GET”那么返回到question.html,否则获取title,detail,author_id,cf,然后加进数据库的question表,返回首页。
评论部分的代码:
@app.route('/answer/', methods=['GET', 'POST'])
def answer():
if request.method == 'POST':
question_id = request.form.get('question_id')
author_id = request.form.get('author_id')
detail = request.form.get('detail')
comment = Comment(question_id=question_id, author_id=author_id, detail=detail)
db.session.add(comment)
db.session.commit()
return redirect(url_for('detail', question_id=question_id))
{% extends 'base.html' %}
{% block title %}
详情页
{% endblock %}
{% block link %}
{% endblock %}
{% block box %}
<div class="container">
<div class="row clearfix">
<div class="col-md-6 column">
<h1 style="color:yellow">{{ ques.title }}</h1>
<div style="padding: 10px;">
<span style="padding-left: 10px;color:yellow">作者:{{ ques.author.username }}</span>
<span style="padding-left: 10px;color:yellow">浏览数:{{ ques.look }}</span>
<span style="padding-left: 10px;color:yellow">点赞数:{{ ques.click }}</span>
<form method="post" style="display: inline-block;padding-left: 10px;">
<input name="click" value="1" type="hidden">
<button>点赞</button>
</form>
<form method="post" style="display: inline-block;padding-left: 10px;">
<input name="collection" value="1" type="hidden">
{% if col %}
<button type="button" disabled>已收藏</button>
{% else %}
<button>收藏</button>
{% endif %}
</form>
</div>
<div style="padding: 70px 20px;margin-bottom: 20px;border:1px solid #eee;">
<p style="color:yellow">
{{ ques.detail }}
</p>
</div>
</div>
<div style="padding: 15px;" class="col-md-6 column">
<h1 style="color:yellow">推荐文章</h1><br>
{% for foo in questions %}
<li class="list-group-item" style="width: 700px">
<a class="wrap-img" href="#" target="_blank">
<img src="{{ url_for('static',filename=foo.author.icon) }}" width="50px">
</a>
<span class="glyphicon glyphicon-left" aria-hidden="true"></span>
<a href="{{ url_for('comment',user_id=foo.author.id ,num='1') }}"
target="_blank">{{ foo.author.username }}</a>
<br>
<a href="{{ url_for('detail',question_id=foo.id) }}">{{ foo.title }}</a>
<span class="badge">{{ foo.creat_time }}</span>
<p style="">{{ foo.detail[0:50] }}...
</p>
</li>
{% endfor %}
</div>
</div>
<br>
<div class="row clearfix">
<div class="col-md-6 column">
<h1 style="color:yellow">评论</h1><br>
<div class="form-group" style="height:100px;width:700px;">
<input type="text" name="author_id" value="{{ user.id }}" hidden>
<input type="text" name="question_id" value="{{ ques.id }}" hidden>
<textarea class="form-control" name="detail" rows="10" style="width:500px;"></textarea>
</div>
<br>
<br>
<br>
<br>
<br>
<div class="form-group">
<button type="submit" class="btn btn-default">发布</button>
</div>
</div>
<div class="col-md-6 column">
<h1 style="color:yellow">用户评论</h1><br>
<ul style="margin-left:0px;">
{% for com in comment %}
<li class="list-group-item">
<h4>{{ com.author.username }}</h4>
<div>
{{ com.detail }}
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endblock %}
{% block script %}
{% endblock %}
代码解析:定义answer方法,如果请求的是“POST”方法,那么获取question_id,author_id,detail,把数据传送到数据库,加入数据库的comment表,返回到detail页面。其中question_id要作为主键。
6、成品展示
首页页面:
注册页面:
密码不一致时
登录页面:
查询功能:
点击发布了的标题:
进入到详情页:
点击收藏:
点击点赞:
发布问答页面:
发布完问答自动回到首页:
评论:
个人信息: