一、系统概要说明:
此网站的设计目的主要是为用户提供一个分享生活趣事的平台,现今,短视频类APP发展迅猛,但文字类分享平台由于微博的存在一直止步不前,但微博已经过于商业化和演艺化,网民急需一个纯净的文字分享平台。此系统中,用户通过注册后不仅能够查看、评论、点赞他人的文章,也可以分享自己的故事,以达到交互的作用。用户还可以在系统内对想要浏览的文章进行关键字搜索和分类搜索,以达到便捷、准确的人性化服务。系统的设计包括用户注册、登录、首页、发帖、搜帖、浏览、点赞、评论、个人中心等等,通过Pycharm和Mysql实现上述功能。
二、网站结构设计:
网站设计了注册、登录功能,以便保存用户个人信息和足迹。本网站以分享为主,为保证用户能够方便快捷的寻找到所需要的文章,网站不仅设计了关键字搜索,还设计了文章分类查找和根据发表年限查找。为体现部分文帖的受众程度,激励用户书写有质量、有意义的文章,网站首页设计了推荐文帖,根据文章的浏览总量进行推荐。文章内部,网站设计了用户可以查看发布的文章的详情内容,阅读后可以增加浏览量,也可以对文章进行点赞、评论和收藏。具体内容和功能如下:
- 用户注册:针对新用户,注册账号时,对密码进行二次验证确认,帐号信息
- 存入数据库;
- 发布文章:用户通过书写标题和正文进行文章发布,并同时选择文章所属类
- 别,方便读者通过分类搜索找到文章;
- 阅读文章:用户通过点击文章标题进入文章详情页,贡献一点阅读量,详情
- 页内,详情页不仅会显示文章的正文,还会注明文章的作者、点赞量、评论情况等,用户自己也可对文章进行评论、点赞、收藏;
- 推荐文章:网站自动根据文章的阅读量进行文章推荐,显示在首页推荐栏中,
- 根据作者的总浏览量将作者名字显示在推荐作者栏中;
- 搜索文章:用户可根据想查看文章的题目进行精确搜索,也可以通过搜索想
- 查看文章的类别或者发表年限进行分类查找;
- 个人中心:用户在个人中心页面可以查看自己所发布的文章、点赞的文章、
- 收藏的文章和评论的文章以及用户个人的帐号、昵称、编号等信息,另此,用户也可在此界面更换头像或者修改密码,点击修改密码,跳转到单独页面,保证了用户个人信息的安全性。
三、网站结构模块图:
四、各模块、页面详解:
- 用户注册,针对新用户,注册账号时,对密码进行二次验证确认,
帐号信息存入数据库;
{% extends 'daohang.html' %}
{% block daohangtitle %}注册{% endblock %}
{% block daohanghead %}
<script src="{
{ url_for('static',filename='js/denglu.js') }}"></script><link href="{
{ url_for('static',filename='css/style.css') }}" rel="stylesheet" type="text/css" media="all"/><link href='//fonts.googleapis.com/css?family=Josefin+Sans:400,100,300,600,700' rel='stylesheet' type='text/css'>
{% endblock %}
{% block daohangbody %}
<div class="login">
<form action="{
{ url_for('zhuce') }}" method="post"><div class="log-input">
<div class="log-input-left">
Username:<input type="text" class="user" name="user" id="user" placeholder="请输入用户名">
</div>
<div class="clear"></div>
</div>
<div class="log-input">
<div class="log-input-left">
Nickname:<input type="text" class="user" name="nickname" id="nickname" placeholder="请输入昵称">
</div>
<div class="clear"></div>
</div>
<div class="log-input">
<div class="log-input-left">
Password:<input type="password" class="lock" name="pass" id="pass" placeholder="请输入密码">
</div>
<div class="clear"></div>
</div>
<div class="log-input">
<div class="log-input-left">
Lnput again:<input type="password" class="lock" name="again" id="again" placeholder="再次输入密码">
</div>
<div class="clear"></div>
</div>
<div id="error_box"><br></div>
<div class="log-input">
<div class="log-input-left">
<input type="submit" value="registration" οnclick="return fnRegistration()">
</div>
</div>
<div class="clear"></div>
</form>
</div>
{% endblock %}
- 首页信息:首页信息包括了搜索、精选文章、精选作者、文章分类搜索、文章发表年限搜索、用户名等:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
{% block daohangtitle %}首页{% endblock %}
</title>
<link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="{
{ url_for('static',filename='css/daohang.css') }}"><link rel="stylesheet" href="{
{ url_for('static',filename='css/wenben.css') }}"><link rel="stylesheet" type="text/css" href="{
{ url_for('static',filename='css/tupian.css') }}"><script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="{
{ url_for('static',filename='js/daohang.js') }}"></script>{% block daohanghead %}{% endblock %}
</head>
<body id="mybody">
<nav class="navbar navbar-inverse" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="{
{ url_for('daohang') }}">首页</a></div>
<div>
<ul class="nav navbar-nav navbar-right">
{% if sessionusername %}
<li><a href="{
{ url_for('yonghu',username_id=sessionuserid,tag=1) }}"οnclick="">{
{ sessionusername }}</a></li><li><a href="{
{ url_for('logout') }}" οnclick=""><span class="glyphicon glyphicon-log-out"></span>注销</a></li>
{% else %}
<li><a href="{
{ url_for('denglu') }}" οnclick=""><span class="glyphicon glyphicon-log-in"></span> 登陆</a></li>
<li><a href="{
{ url_for('zhuce') }}" οnclick=""><span class="glyphicon glyphicon-user"></span>注册</a></li>
{% endif %}
</ul>
</div>
<div style="float: right">
<img id="myonoff" οnclick="mySwitch()" src="http://www.runoob.com/images/pic_bulbon.gif" style="width:40px">
</div>
<div>
<ul class="nav navbar-nav">
<li><a href="{
{ url_for('fabu') }}" οnclick="">发布</a></li></ul>
<ul class="nav navbar-nav">
{% if sessionuserid %}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
设置 <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="{
{ url_for('yonghu',username_id=sessionuserid,tag=1) }}">个人信息</a></li><li class="divider"></li>
<li><a href="{
{ url_for('password_update',user_id=sessionuserid) }}">修改密码</a></li><li><a href="{
{ url_for('yonghu',username_id=sessionuserid,tag=4) }}">收藏</a></li><li><a href="#">搜索</a></li>
</ul>
</li>
<li><a href="#">||</a></li>
{% else %}
<li></li>
{% endif %}
</ul>
</div>
<form class="form-inline" role="form" action="{
{ url_for('search') }}" method="get"><div class="form-group">
<label class="sr-only" for="sousuo">名称</label>
<input type="text" class="form-control" name="sousuo" id="sousuo" placeholder="请输入内容">
<input type="submit" value="搜索" class="btn btn-default" οnclick="">
</div>
</form>
</div>
</nav>
<nav class="navbar navbar-inverse navbar-fixed-bottom" role="navigation">
</nav>
<div id="navtop"></div>
{% block daohangbody %}
<div class="container">
<div class="row clearfix">
<div class="daohang-1">
<br>
<br>
<table class="table table-hover">
<thead>
<tr>
<th>
<small>推荐作者</small>
</th>
</tr>
</thead>
<tbody>
{% for foo in author %}
<tr>
<td><a href="{
{ url_for('yonghu',username_id=foo.id,tag=1) }}">{ { foo.nickname }}</a></td><td><em>
<small>文章数:{ { foo.fabu | length }}</small>
</em></td>
</tr>
{% endfor %}
</tbody>
</table>
<table class="table table-hover">
<thead>
<tr>
<th>
<small>推荐文章</small>
</th>
</tr>
</thead>
<tbody>
{% for foo in ydfabu %}
<tr>
<td><a href="{
{ url_for('fabuview',fabu_id=foo.id) }}">{ { foo.title }}</a></td><td><span class="glyphicon glyphicon-eye-open"></span><em>
<small>浏览:{ { foo.yuedu }}</small>
</em></td>
</tr>
{% endfor %}
</tbody>
</table>
<br>
<br>
<br>
</div>
<div class="daohang-2">
<div>
{% for foo in fabus %}
<div class="fabukuai">
<div class="daohang-touxiang">
{% if foo.author.img is none %}
<a href="{
{ url_for('yonghu',username_id=foo.author_id,tag=1) }}"><img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3298685419,1477967578&fm=27&gp=0.jpg"
style="width: 50px">
</a>
{% else %}
<a href="{
{ url_for('yonghu',username_id=foo.author_id,tag=1) }}"><img src="/static/{
{ foo.author.img }}" style="width: 50px"></a>
{% endif %}
</div>
<div class="daohang-neirong">
<h4><a
href="{
{ url_for('fabuview',fabu_id=foo.id) }}">{ { foo.title }}</a></h4><p>
<a href="{
{ url_for('yonghu',username_id=foo.author_id,tag=1) }}"><spanclass="glyphicon glyphicon-user"></span>{
{ foo.author.nickname }}</a><span>{
{ foo.creat_time }}</span><span>{
{ foo.leixing }}</span><span class="glyphicon glyphicon-thumbs-up neirong-right">{
{ foo.dianzangs|length }}</span><span class="glyphicon glyphicon-comment neirong-right">{
{ foo.comments|length }} </span><span class="glyphicon glyphicon-eye-open neirong-right">{
{ foo.yuedu }} </span></p>
<div class="clear"></div>
<hr>
</div>
<div class="clear"></div>
{# <div class="bq"><p>{
{ foo.detail|safe }}</p></div>#}
</div>
{% endfor %}
</div>
</div>
<div class="daohang-3">
<h3 class="text-center">文章类型</h3>
<div class="fl">
<form class="form-horizontal" role="form" action="{
{ url_for('fenlei') }}" method="get"><div class="form-group">
<input type="submit" value="散文" id="fenlei" name="fenlei" class="btn btn-default">
<input type="submit" value="诗歌" id="fenlei" name="fenlei" class="btn btn-default">
<input type="submit" value="科普" id="fenlei" name="fenlei" class="btn btn-default">
<input type="submit" value="历史" id="fenlei" name="fenlei" class="btn btn-default">
<input type="submit" value="电影" id="fenlei" name="fenlei" class="btn btn-default">
<br>
<br>
<input type="submit" value="人文" id="fenlei" name="fenlei" class="btn btn-default">
<input type="submit" value="小说" id="fenlei" name="fenlei" class="btn btn-default">
<input type="submit" value="摄影" id="fenlei" name="fenlei" class="btn btn-default">
<input type="submit" value="旅行" id="fenlei" name="fenlei" class="btn btn-default">
<input type="submit" value="文化" id="fenlei" name="fenlei" class="btn btn-default">
<br>
<br>
</div>
</form>
<hr>
<h3 class="text-center">时间</h3>
<form class="form-horizontal" role="form" action="{
{ url_for('fenlei') }}" method="get"><div class="form-group">
<input type="submit" value="2015" id="fenlei" name="fenlei" class="btn btn-success">
<input type="submit" value="2016" id="fenlei" name="fenlei" class="btn btn-info">
<input type="submit" value="2017" id="fenlei" name="fenlei" class="btn btn-warning">
<input type="submit" value="2018" id="fenlei" name="fenlei" class="btn btn-danger">
</div>
</form>
<hr>
</div>
</div>
<div class="clear"></div>
</div>
</div>
{% endblock %}
</body>
</html>
- 用户登录:
{% extends 'daohang.html' %}
{% block daohangtitle %}登陆{% endblock %}
{% block daohanghead %}
<script src="{
{ url_for('static',filename='js/denglu.js') }}"></script><link href="{
{ url_for('static',filename='css/style.css') }}" rel="stylesheet" type="text/css" media="all"/><link href='//fonts.googleapis.com/css?family=Josefin+Sans:400,100,300,600,700' rel='stylesheet' type='text/css'>
{% endblock %}
{% block daohangbody %}
<div class="login">
<form action="{
{ url_for('denglu') }}" method="post"><div class="log-input">
<div class="log-input-left">
Username:<input type="text" class="user" name="user" id="user" placeholder="请输入用户名">
</div>
</div>
<div class="log-input">
<div class="log-input-left">
Password:<input type="password" class="lock" name="pass" id="pass" placeholder="请输入密码">
</div>
</div>
<div id="error_box"><br></div>
<div class="log-input">
<div class="log-input-left">
<input type="submit" value="login" οnclick="return fnLogin()">
</div>
</div>
<div class="clear"></div>
</form>
</div>
{% endblock %}
- 发布详情页:用户通过书写标题和正文进行文章发布,并同时选
择文章所属类别,方便读者通过分类搜索找到文章;
{% extends 'daohang.html' %}
{% block daohangtitle %}发布{% endblock %}
{% block daohanghead %}
<link href="{
{ url_for('static',filename='css/style.css') }}" rel="stylesheet" type="text/css" media="all"/><script src=" /static/ueditor/ueditor.config.js "></script>
<script src="/static/ueditor/ueditor.all.min.js"></script>
<script type="text/javascript" src="/static/js/ueditor.js"></script>
{% endblock %}
{% block daohangbody %}
<form role="form" action="{
{ url_for('fabu') }}" method="post"><div class="col-md-3 column"></div>
<div class="form-group col-md-6 column">
<label for="title">标题</label>
<textarea class="form-control" rows="1" id="title" name="title"></textarea>
<label for="detail">详情</label>
<script id="editor" type="text/plain" name="detail"></script>
{# <textarea class="form-control" rows="10" id="detail" name="detail"></textarea>#}
<div class="log-input">
<label for="lastname" class=" control-label"></label>
<div class="">
<select class="" name="leixing" id="leixing">
<option value="None" selected>请选择类型</option>
<option value="散文">散文</option>
<option value="诗歌">诗歌</option>
<option value="科普">科普</option>
<option value="历史">历史</option>
<option value="电影">电影</option>
<option value="人文">人文</option>
<option value="小说">小说</option>
<option value="摄影">摄影</option>
<option value="旅行">旅行</option>
<option value="文化">文化</option>
</select>
</div>
</div>
<div id=""><br></div>
<input type="submit" value="发布" class="btn btn-default" οnclick="">
</div>
<div class="col-md-3 column"></div>
</form>
{% endblock %}
- 阅读文章:用户通过点击文章标题进入文章详情页,贡献一点阅
读量,详情页内,详情页不仅会显示文章的正文,还会注明文章的作者、点赞量、评论情况等,用户自己也可对文章进行评论、点赞、收藏;
{% extends 'daohang.html' %}
{% block daohangtitle %}发布详情{% endblock %}
{% block daohanghead %}
<script src=" /static/ueditor/ueditor.config.js "></script>
<script src="/static/ueditor/ueditor.all.min.js"></script>
<script type="text/javascript" src="/static/js/ueditor.js"></script>
<style type="text/css">
{# .list-unstyled img{#}
{# height: 50px;#}
{# width: 50px;#}
{# }#}
</style>
{% endblock %}
{% block daohangbody %}
<div class="col-md-3 column "></div>
<div class="col-md-6 column ">
<h2 href="#" class="text-center">{
{ fa.title }}</h2><br>
<p class="text-center">
<a href="{
{ url_for('yonghu',username_id=fa.author_id,tag=1) }}"><small>{
{ fa.author.username }}</small></a>
<span class="pull-center"><small>{
{ fa.creat_time }}</small></span><span class="glyphicon glyphicon-eye-open"></span><em>浏览:{ { fa.yuedu }}</em>
<span class=""></span><em>评论:{ { fa.comments|length }}</em>
<span class=""></span><em>点赞:{ { fa.dianzangs|length }}</em>
</p>
<hr>
<div class="bq"><p>{
{ fa.detail|safe }}</p></div>
<form action="{
{ url_for('dianzang') }}" method="post"><input type="hidden" name="dzfabu_id" value="{
{ fa.id }}"><input type="hidden" name="dzuser_id" value="{
{ sessionuserid }}">{% if dzyes %}
<button type="button" class="btn btn-default btn-xs pull-right"><span
class="glyphicon glyphicon-heart">{
{ fa.dianzangs |length }}</span></button>{% else %}
<button type="submit" class="btn btn-success btn-xs pull-right"><span
class="glyphicon glyphicon-heart-empty">赞</span></button>
{% endif %}
</form>
<form action="{
{ url_for('shoucang') }}" method="post"><input type="hidden" name="scfabu_id" value="{
{ fa.id }}"><input type="hidden" name="scuser_id" value="{
{ sessionuserid }}">{% if yes %}
<button type="button" class="btn btn-default btn-xs pull-right">已收藏</button>
{% else %}
<button type="submit" class="btn btn-primary btn-xs pull-right">+收藏</button>
{% endif %}
</form>
<hr>
<form action="{
{ url_for('comment') }}" method="post"><div class="form-group">
<script id="editor" type="text/plain" name="pinglun"></script>
{# <textarea name="pinglun" class="form-control" rows="5" id="pinglun"#}
{# placeholder="请输入评论"></textarea>#}
<input type="hidden" name="fa_id" value="{
{ fa.id }}"></div>
<button type="submit" class="btn btn-default">发送</button>
<br>
<br>
<h4>评论:({ { fa.comments|length }})</h4>
<ul class="list-unstyled bq">
{% for foo in fa.comments %}
<li class="list-group-item">
<a href="{
{ url_for('yonghu',username_id=foo.author_id,tag=1) }}"><spanclass="glyphicon glyphicon-fire"></span>{
{ foo.author.username }}</a><span class="badge pull-right">{
{ foo.creat_time }}</span><p>{
{ foo.detail|safe }}</p><br>
</li>
{% endfor %}
</ul>
</form>
<br>
<br>
<br>
</div>
<div class="col-md-3 column "></div>
{% endblock %}
- 个人中心:用户在个人中心页面可以查看自己所发布的文章、点
赞的文章、收藏的文章和评论的文章以及用户个人的帐号、昵称、编号等信息,另此,用户也可在此界面更换头像或者修改密码,点击修改密码,跳转到单独页面,保证了用户个人信息的安全性。
(1) 个人信息:
{% extends 'yonghufather.html' %}
{% block yonghubody %}
<h3 class="">个人信息</h3>
<ul class="list-unstyled nav1">
<li class="">用户:{ { username }}</li>
<li class="">编号:{ { userid }}</li>
<li class="">昵称:{ { nickname }}</li>
<li class="">头像:
{% if img is none%}
<img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3298685419,1477967578&fm=27&gp=0.jpg"
style="width: 100px">
{% else %}
<img src="/static/{
{ img }}"style="width: 100px">
{% endif %}
{% if sessionusername %}
<form action="{
{ url_for('uploadLogo',user_id=userid) }}" method="post" enctype="multipart/form-data"><input type="file" name="logo" required>
<button type="submit">上传头像</button>
</form>
{% else %}
<span></span>
{% endif %}
</li>
<li class="">文章:{ { fabus|length }}篇</li>
<li class="">评论:{ { comments|length }}条</li>
<li class="">收藏文章:{ { shoucang|length }}篇</li>
</ul>
(2) 发布信息:
{% extends 'yonghufather.html' %}
{% block yonghubody %}
<div>
<h3 class="text-center">全部发布信息({ { fabus|length }})</h3>
<ul class="list-unstyled bq">
{% for foo in fabus %}
<li class="list-group-item">
<a href="{
{ url_for('yonghu',username_id=foo.author_id,tag=1) }}"><spanclass="glyphicon glyphicon-fire"></span>{
{ foo.author.username }}</a><span class="badge">{
{ foo.creat_time }}</span><span class="badge pull-right">{
{ foo.leixing }}</span><h4 class="text-center"><a href="{
{ url_for('fabuview',fabu_id=foo.id) }}">{ { foo.title }}</a></h4>
<br>
<p>{
{ foo.detail|safe }}</p></li>
{% endfor %}
</ul>
<br>
<br>
<br>
</div>
{% endblock %}
(3) 评论信息:
{% extends 'yonghufather.html' %}
{% block yonghubody %}
<div>
<h3 class="text-center">全部评论信息({ { comments|length }})</h3>
<ul class="list-unstyled bq">
{% for foo in comments %}
<li class="list-group-item">
<a href="{
{ url_for('yonghu',username_id=foo.author_id,tag=1) }}"><spanclass="glyphicon glyphicon-fire"></span>{
{ foo.author.username }}</a><span class="badge pull-right">{
{ foo.creat_time }}</span><p>{
{ foo.detail|safe }}</p><br>
</li>
{% endfor %}
</ul>
<br>
<br>
<br>
</div>
{% endblock %}
(4) 收藏文章:
{% extends 'yonghufather.html' %}
{% block yonghubody %}
<div>
<h3>收藏文章({ { shoucang|length }})</h3>
<hr>
<table class="table table-bordered">
<thead>
<tr>
<th>文章</th>
<th>作者</th>
</tr>
</thead>
<tbody>
{% for foo in shoucang %}
<tr>
<td><a href="{
{ url_for('fabuview',fabu_id=foo.fabu.id) }}">{ { foo.fabu.title }}</a> <em>浏览:{ { foo.fabu.yuedu }} 评论:{ { foo.fabu.comments |length }} 点赞:{ { foo.fabu.dianzangs |length }}</em></td><td><a href="{
{ url_for('yonghu',username_id=foo.author.id,tag=1) }}">{ { foo.author.username }}</a></td></tr>
{% endfor %}
</tbody>
</table>
<br>
<br>
<br>
</div>
{% endblock %}
(5) 修改密码:
{% extends 'daohang.html' %}
{% block daohangtitle %}密码修改{% endblock %}
{% block daohanghead %}{% endblock %}
{% block daohangbody %}
<form class="form-horizontal" role="form" action="{
{ url_for('password_update1') }}" method="post"><div class="col-md-3 column"></div>
<div class="col-md-6 column bk">
<h3 class="text-center">密码修改</h3>
<hr>
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户账号</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="username" name="username"
value="{
{ users.username }}" readonly></div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">新密码</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="password" name="password" placeholder="请输入新密码"
required>
</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>
</div>
<div class="col-md-3 column"></div>
</form>
{% endblock %}
五、系统实现详解:
from flask import Flask, render_template, request, redirect, url_for, session
from flask_sqlalchemy import SQLAlchemy
import config, os
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__) # 创建Flask对象
app.config.from_object(config) # 关联config.py文件进来
db = SQLAlchemy(app) # 建立和数据库的关系映射
class User(db.Model): # 创建类User
__tablename__ = 'user' # 类对应的表名user
id = db.Column(db.Integer, primary_key=True, autoincrement=True) # autoincrement自增长
username = db.Column(db.String(20), nullable=False) # nullable是否为空
_password = db.Column(db.String(200), nullable=False) # 密码加密内部使用
nickname = db.Column(db.String(20), nullable=True)
img = db.Column(db.String(100))
@property # 定义函数,需要用属性时可以用函数代替
def password(self): # 密码加密外部使用
return self._password
@password.setter
def password(self, row_password): # 密码进来时进行加密,generate_password_hash是一个密码加盐哈希函数,生成的哈希值可通过check_password_hash()进行验证。
self._password = generate_password_hash(row_password)
def check_password(self, row_password): # check_password_hash函数用于验证经过generate_password_hash哈希的密码。若密码匹配,则返回真,否则返回假。
result = check_password_hash(self._password, row_password)
return result
class Fabu(db.Model): # 问答
__tablename__ = 'fabu'
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)
leixing = db.Column(db.String(20), nullable=True)
creat_time = db.Column(db.DateTime, default=datetime.now) # 提交时间会自己赋值
author_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 数据类型是db.Integer,db.ForeignKey参数指定外键是哪个表中哪个id
author = db.relationship('User', backref=db.backref('fabu')) # 建立关联,其author属性将返回与问答相关联的用户实例,相当于数据库中的表连接
# 第一个参数表明这个关系的另一端是哪个类,第二个参数backref,将向User类中添加一个fabu属性,从而定义反向关系,这一属性可访问Fabu类,获取的是模型对象
yuedu = db.Column(db.Integer, nullable=False)
class Shoucang(db.Model): # 收藏
__tablename__ = 'shoucang'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
fabu_id = db.Column(db.Integer, db.ForeignKey('fabu.id'))
fabu = db.relationship('Fabu', backref=db.backref('shoucangs'))
author = db.relationship('User', backref=db.backref('shoucangs'))
class Dianzang(db.Model): # 点赞
__tablename__ = 'dianzang'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
fabu_id = db.Column(db.Integer, db.ForeignKey('fabu.id'))
fabu = db.relationship('Fabu', backref=db.backref('dianzangs'))
author = db.relationship('User', backref=db.backref('dianzangs'))
db.create_all() # 测试是否连接成功
'''
# 插入功能
user = User(username='15',password='12')
db.session.add(user)
db.session.commit()
# 查询功能
user=User.query.filter(User.username=="15").first()
print(user.username,user.password)
# 修改功能
user=User.query.filter(User.username=="15").first()
user.password='888'
db.session.commit()
# 删除功能
user=User.query.filter(User.username=="15").first()
db.session.delete(user)
db.session.commit()
'''
# session会话连接
# filter()过滤器
# route制定路径和函数之间的关系
# def定义一个变量
# 跳转首页。
@app.route('/')
def daohang():
context = {
'fabus': Fabu.query.order_by('-creat_time').all(),
'author': User.query.all(),
'ydfabu': Fabu.query.filter(Fabu.yuedu > 5).all() # 当发布的文章阅读量大于多少时取出这些文章,显示在首页的推荐文章
# order_by('-creat_time')按时间降序排列,Fabu.query.all()查出了Fabu类的所有元组
}
return render_template('daohang.html', **context)
# 跳转测试。
@app.route('/lin/')
def lin():
return 'lin'
# 跳转登陆。
@app.route('/denglu/', methods=['GET', 'POST']) # methods定义它有两种请求方式
def denglu():
if request.method == 'GET':
return render_template('denglu.html')
else:
username = request.form.get('user') # post请求模式,安排对象接收数据
password = request.form.get('pass')
user = User.query.filter(User.username == username).first() # 作查询,并判断
if user: # 判断用户名
if user.check_password(password): # 判断密码
session['user'] = username # 利用session添加传回来的值username
session['user_id'] = user.id
session.permanent = True # 设置session过期的时间
return redirect(url_for('daohang'))
else:
return u'用户密码错误'
else:
return u'用户不存在,请先注册'
# 跳转密码修改页。
@app.route('/password_update/<user_id>')
def password_update(user_id):
users = User.query.filter(User.id == user_id).first() # 查询出要修改密码的该用户
return render_template('password_update.html', users=users)
# 跳转修改密码后接受数据。
@app.route('/password_update1/', methods=['POST'])
def password_update1():
username = request.form.get('username') # 接收username的值,知道要修改的是哪个用户
password = request.form.get('password')
users = User.query.filter(User.username == username).first() # 查询出要修改用户的整条信息
users.password = password # 执行修改
db.session.commit()
return redirect(url_for('yonghu', username_id=users.id, tag='1'))
@app.context_processor # 上下文处理器,定义变量然后在所有模板中都可以调用,类似idea中的model
def mycontext():
user = session.get('user')
user_id = session.get('user_id')
if user:
return {'sessionusername': user, 'sessionuserid': user_id} # 包装到username,在所有html模板中可调用
else:
return {} # 返回空字典,因为返回结果必须是dict
# 跳转注销。
@app.route('/logout')
def logout():
session.clear() # 注销时删除所有session
return redirect(url_for('daohang'))
# 跳转注册。
@app.route('/zhuce/', methods=['GET', 'POST']) # methods定义它有两种请求方式,因为它在表单的请求是post,类似我们在idea中的sava请求模式
def zhuce():
if request.method == 'GET':
return render_template('zhuce.html')
else:
username = request.form.get('user') # post请求模式,安排对象接收数据
password = request.form.get('pass')
nickname = request.form.get('nickname')
user = User.query.filter(User.username == username).first() # 作查询,并判断
if user:
return u'该用户已存在'
else:
user = User(username=username, password=password, nickname=nickname) # 将对象接收的数据赋到User类中,即存到数据库
db.session.add(user) # 执行操作
db.session.commit()
return redirect(url_for('denglu')) # redirect重定向
# 跳转某页面之前先进行登录。定义decorator可以增强函数功能,装饰器本身是函数,入参是函数,返回值也是函数
def loginFirst(fabu):
@wraps(fabu) # 加上wraps,它可以保留原有函数的__name__,docstring
def wrapper(*args, **kwargs): # 定义wrapper函数将其返回,用*args, **kwargs把原函数的参数进行传递
if session.get('user'): # 只有经过登陆,session才能记住并get到值
return fabu(*args, **kwargs)
else:
return redirect(url_for('denglu'))
return wrapper
# 跳转图片。
@app.route('/tupian/')
def tupian():
return render_template('tupian.html')
# 跳转发布。
@app.route('/fabu/', methods=['GET', 'POST']) # methods定义它有两种请求方式
@loginFirst # 将decorator定义的增强函数放在待增强函数定义的上面
def fabu():
if request.method == 'GET':
return render_template('fabu.html')
else:
title = request.form.get('title') # post请求模式,安排对象接收数据
detail = request.form.get('detail')
leixing = request.form.get('leixing')
yuedu = 0
author_id = User.query.filter(
User.username == session.get('user')).first().id # 将session get到的user进行查询并取出id放到外键author_id中
fabu = Fabu(title=title, detail=detail, author_id=author_id, leixing=leixing,
yuedu=yuedu) # 将对象接收的数据赋到Fabu类中,即存到数据库
db.session.add(fabu) # 执行操作
db.session.commit() # 提交到数据库
return redirect(url_for('daohang')) # redirect重定向
# 跳转发布详情
@app.route('/fabuview/<fabu_id>') # 和idea的update一样,将id带到控制器
def fabuview(fabu_id):
yes = Shoucang.query.filter( # yes用在用户详情页判断是否已收藏的按钮
and_(
Shoucang.author_id == session.get('user_id'), Shoucang.fabu_id == fabu_id
)
).first()
dzyes = Dianzang.query.filter( # dzyes用在用户详情页判断是否已点赞的按钮
and_(
Dianzang.author_id == session.get('user_id'), Dianzang.fabu_id == fabu_id
)
).first()
fa = Fabu.query.filter(Fabu.id == fabu_id).first() # 根据主页带回来的id查询出整条元组记录,丢进fa
comments = Comment.query.filter(Comment.fabu_id == fabu_id).all() # 根据带回来的Fabu的id在Comment查询出所有评论
fa.yuedu = fa.yuedu + 1 # 定义浏览功能,每次进去详情页,浏览次数加1
db.session.commit()
return render_template('fabuview.html', fa=fa, comments=comments, yes=yes,
dzyes=dzyes) # 把值fa丢进键fa,在fabuview.html页面调用
# 方法二:
# fabu={
# 'fa':Fabu.query.filter(Fabu.id == fabu_id).first()
# }
# return render_template('fabuview.html',**fabu)
# 跳转评论。
@app.route('/comment/', methods=['POST'])
@loginFirst # 装饰器,跳转某页面之前先进行登录
def comment():
detail = request.form.get('pinglun') # post请求模式,安排对象接收数据
author_id = User.query.filter(User.username == session.get('user')).first().id
fabu_id = request.form.get('fa_id')
comment = Comment(detail=detail, author_id=author_id, fabu_id=fabu_id) # 将对象接收的数据赋到Comment类中,即存到数据库
db.session.add(comment) # 执行操作
db.session.commit() # 提交到数据库
return redirect(url_for('fabuview', fabu_id=fabu_id)) # 重定向到fabuview请求时要带fabu_id
# 跳转用户详情
@app.route('/yonghu/<username_id>/<tag>') # 为了把页面分开,我们在html页面传了一个tag参数
def yonghu(username_id, tag):
user = User.query.filter(User.id == username_id).first()
shoucang = Shoucang.query.filter(Shoucang.author_id == username_id).all()
context = {
'userid': user.id,
'username': user.username,
'nickname': user.nickname,
'fabus': user.fabu,
'comments': user.comments,
'shoucang': shoucang,
'img': user.img
} # 根据tag的不同去到不同页面,一个请求跳转3个不同页面
if tag == '1':
return render_template('yonghu1.html', **context)
elif tag == '2':
return render_template('yonghu2.html', **context)
elif tag == '3':
return render_template('yonghu3.html', **context)
else:
return render_template('yonghu4.html', **context)
# @app.route('/yonghu2/<username_id>')
# def yonghu2(username_id):
# user = User.query.filter(User.id == username_id).first()
# context = {
# 'userid':user.id,
# 'username':user.username,
# 'fabus':user.fabu,
# 'comments':user.comments
# }
# return render_template('yonghu2.html',**context)
#
#
# @app.route('/yonghu3/<username_id>')
# def yonghu3(username_id):
# user = User.query.filter(User.id == username_id).first()
# context = {
# 'userid':user.id,
# 'username':user.username,
# 'fabus':user.fabu,
# 'comments':user.comments
# }
# return render_template('yonghu3.html',**context)
# 跳转首页搜索
@app.route('/search/')
def search():
sousuo = request.args.get('sousuo') # args获取关键字,区别form
author = User.query.all()
ydfabu = Fabu.query.filter(Fabu.yuedu > 5).all()
fabus = Fabu.query.filter(
or_( # 两种查询条件
Fabu.title.contains(sousuo), # contains模糊查
Fabu.detail.contains(sousuo)
)
).order_by('-creat_time')
return render_template('daohang.html', fabus=fabus, author=author, ydfabu=ydfabu) # fabus要和原首页数据模型一样
# 跳转高级分类查询
@app.route('/fenlei/')
def fenlei():
fenlei = request.args.get('fenlei') # args获取关键字,区别form
author = User.query.all()
ydfabu = Fabu.query.filter(Fabu.yuedu > 5).all()
fenlei_fabus = Fabu.query.filter(
or_( # 两种查询条件
Fabu.title.contains(fenlei), # contains模糊查
Fabu.leixing.contains(fenlei),
Fabu.creat_time.contains(fenlei)
)
).order_by('-creat_time')
return render_template('daohang.html', fabus=fenlei_fabus, author=author, ydfabu=ydfabu) # fabus要和原首页数据模型一样
# 跳转文章收藏
@app.route('/shoucang/', methods=['POST'])
@loginFirst
def shoucang():
scfabu_id = request.form.get('scfabu_id')
scuser_id = request.form.get('scuser_id')
shoucang = Shoucang(fabu_id=scfabu_id, author_id=scuser_id)
db.session.add(shoucang) # 执行操作
db.session.commit() # 提交到数据库
return redirect(url_for('fabuview', fabu_id=scfabu_id))
# 跳转文章点赞
@app.route('/dianzang/', methods=['POST'])
@loginFirst
def dianzang():
dzfabu_id = request.form.get('dzfabu_id')
dzuser_id = request.form.get('dzuser_id')
dianzang = Dianzang(fabu_id=dzfabu_id, author_id=dzuser_id)
db.session.add(dianzang) # 执行操作
db.session.commit() # 提交到数据库
return redirect(url_for('fabuview', fabu_id=dzfabu_id))
# 上传头像
@app.route('/uploadLogo/<user_id>', methods=['GET', 'POST'])
def uploadLogo(user_id):
user = User.query.filter(User.id == user_id).first()
f = request.files['logo']
basepath = os.path.dirname(__file__) # 当前文件所在路径
upload_path = os.path.join(basepath, 'static/img', f.filename) # 注意:没有的文件夹一定要先创建,不然会提示没有该路径
f.save(upload_path)
user.img = 'img/' + f.filename
db.session.commit()
return redirect(url_for('yonghu', username_id=user_id, tag=1))
if __name__ == '__main__':
app.run(debug=True)
六、网站页面展示: