此网站系统具有:
a.注册、登录、注销
b.发布、列表显示
c.详情页
d.评论、列表显示
e.个人中心
f.搜索,条件组合搜索
g.文章分类、显示
h.点赞、收藏
i.修改密码、头像、上传头像
g.我的发布、点赞、收藏、评论
k.高级搜索
l.热门文章、推荐文章等功能。
本系统使用Pycharm开发工具利用flask框架进行开发。
使用AJAX技术进行页面前端数据传输,后台根据获取数据进行json判断,并在页面进行弹框提示。
此网站采用div+css进行布局,背景采用古风图片,使其增加韵味。
a.上传头像功能
在用户表中添加了一个存储头像图片路径的列,将页面上传的图片的内容存储到后台给的路径中,并在页面中根据其具体路径显示头像,用户没有上传头像的时候则放置默认的头像。
代码如下:
@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));
html:
<li class="list-group-item-danger">头像: {% 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 %} <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> </li>
b.点赞、收藏
点赞收藏功能都是需要建立点赞表和收藏表,获取到用户的id与帖子的id再进行是否在数据库中有此数据进行判断是否可以进行点赞和收藏的操作。
# 跳转文章收藏 @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))
html
<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>
c.分类功能
分类功能需要我们添加一个版块分类的模型和数据库,记录版块id版块的名称和时间,再在帖子表中加入其版块id的外键,在发布帖子中记录下版块的id。
@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要和原首页数据模型一样
d.修改密码
利用Ajax技术进行页面传值。
@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
用户信息表
id:用户id(主键、自增长、默认值为shortuuid)
username:用户名(列属性、String类型、不可为空)
_password:用户密码(列属性、String类型、不可为空,设置哈希加密)
email:邮箱(列属性、String类型、不可重复、不可为空)
realname:真实姓名(列属性、String类型)
avatar:用户头像(列属性、String类型)
signature:个性签名(列属性、String类型)
join_time:加入时间(列属性、DateTime类型,默认值为添加时间)
美文发布表
id:帖子id(主键、Int类型、自增长)
title:帖子标题(列属性、String类型、不可为空)
content:内容(列属性、Text类型、不可为空)
create_time:创建时间(列属性、DateTime类型、默认值为创建时间)
board_id:板块id(外键、Int类型、外键为border.id)
author_id:作者id(外键、String类型、外键为front_user.id)
评论表
id:帖子id(主键、Int类型、自增长)
content:内容(列属性、Text类型、不可为空)
create_time:创建时间(列属性、DataTime类型、默认值为创建时间)
post_id:帖子id(外键、Int类型、外键为post.id)
author_id:用户id(外键、String类型、外键为front_user.id)
板块表
id:板块id(主键、Int类型、自增长)
name:板块名称(列属性、String类型、不可为空)
create_time:创建时间(列属性、DataTime、默认值为创建时间)
点赞表
id:板块id(主键、Int类型、自增长)
post_id:帖子id(外键、Int类型、外键为post.id)
user_id:用户id(外键、String类型、外键为front_user.id)
收藏表
id:板块id(主键、Int类型、自增长)
user_id :用户id(外键、String类型、外键为front_user.id)
post_id:帖子id(外键、Int类型、外键为post.id)
create_time:创建时间(列属性、DateTime,默认值创建时间)
关键算法if根据前端传到的数据在后台进行比对,再根据传输的code的值进行判断,再根据js文件的判断,在页面上展示出不同的效果。
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),default=None)
后台视图会根据表单验证判断结果返回出不同种类的方法回调,输出不同的code值。
# 跳转注册。 @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
@bp.route(‘/‘) def index(): board_id = request.args.get(‘bd‘,type=int,default=None) page = request.args.get(get_page_parameter(),type=int, default=1) boards = BoardModel.query.all() start =(page-1)*config.PER_PAGE end = start + config.PER_PAGE posts=None total = 0 query_obj=PostModel.query.order_by(PostModel.create_time.desc()) if board_id: query_obj = query_obj.filter_by(board_id=board_id) posts = query_obj.slice(start,end) total = query_obj.count() else: posts = query_obj.slice(start,end) total = query_obj.count() pagination = Pagination(bs_version=3,page=page,total=total,outer_window=0,inner_window=2) context={ ‘boards‘: boards, ‘posts‘:posts, ‘pagination‘:pagination, ‘current_board‘:board_id } return render_template(‘front/front_index.html‘,**context)
@bp.before_request def my_before_request(): if config.FRONT_USER_ID in session: user_id = session.get(config.FRONT_USER_ID) user = FrontUser.query.get(user_id) if user: g.front_user = user
原文:https://www.cnblogs.com/lzp963/p/9190817.html