Flask + vue 前后端分离的 二手书App

一个Flask + vue 前后端分离的 二手书App

效果展示:
https://blog.csdn.net/qq_42239520/article/details/88534955

所用技术清单
在这里插入图片描述
项目地址:项目地址
vue代码地址:vue代码地址

项目部分过程笔记:

后台:

项目结构

Secondhanbook /   项目目录apps v1__init__.py 导入 urlsurls.py  路由配置forms.pymodels.pyviewsuser_views.py  用户相关视图book_vews.py 书籍相关视图config.py  配置文件run.py  项目启动文件manage.py  数据库迁移文件Secondhanbook.py  初始化文件 utils  工具类目录............          

1. Flask_RESTful 的返回 和 缓存时候的自定义返回

flask_restful 在视图方法上加上marshal_with 装饰器,并传递你返回的模式。但当自定义时,需要返回自己的模式

return marshal(books,self.resource_fields,envelope='data')resource_fields:自定义返回模式data:  返回时,数据包装

2. 使用Flask_RESTful 下表单验证以及csrf防御

每当用户进入提交Post请求的页面,实例化一个表单form,返回csrf_token

csrf_token = form.csrf_token.current_tokenreturn restful.success(data=csrf_token)

3.路由配置

api = Api(prefix='/api')
#用户相关
api.add_resource(Login,'/login/',endpoint='login')  
......
#书籍相关
api.add_resource(BookAddView,'/bookadd/',endpoint='bookadd')
......

4.使用itsdangerous生成临时身份令牌
生成令牌

    def generate_auth_token(self,expiration=172800):#两天过期s = Serializer(config.BaseConfig.SECRET_KEY,expires_in=expiration)return s.dumps({'id':self.id})

身份检验

    def verify_auth_token(token):s = Serializer(config.BaseConfig.SECRET_KEY)try:data = s.loads(token)except Exception as e:return Noneuser = FrontUserModel.query.get(data['id'])return user

5.配置文件的书写方式,类继承的方式

class BaseConfig(object):pass
class DevelopmentConfig(BaseConfig):pass
class OnlineConfig(BaseConfig):pass    

6. celery 处理费时任务

@celery.task
def send_mail(subject,recipients,user_id):......
@celery.task
def BookCacheAdd(books):......

7.redis 存储数据bytes 问题解决

cache = redis.StrictRedis(host='127.0.0.1',port=6379,db=0,decode_responses=True)

8. 封装jsonfy的返回

class HttpCode(object):Ok = 200ParamerError = 400Unauth = 401ServerError = 500
def RestfulResult(code,message,data):return jsonify({'code':code,'message':message,'data':data})
def success(message="",data=None):return RestfulResult(HttpCode.Ok,message=message,data=data)
......

9.对axios 提交bytes类型数据进行form验证

from werkzeug.datastructures import MultiDict......myform = json.loads((request.data.decode('utf-8')))form = LoginForm(MultiDict(myform))......

10. flask 接收 接收多个文件axios 上传的多个文件


**  AddBookView  ** files = request.filesfor file in files.values():filename = upload.change_filename(secure_filename(file.filename))**upload.vue**for (var i = 0; i < this.files.length; i++) {this.formdata.append('file' + i, this.files[i])}axios.post('api/bookadd/', this.formdata, {headers: {'Content-Type': 'multipart/form-data'}}).then(this.handleAxiosDone)

11.表单对files, 输入字段验证

from werkzeug.datastructures import CombinedMultiDict
form = Yourform(CombinedMultiDict([request.form,   request.files])) //  合并 数据和文件
文件验证:
定义表单时,采用FileField这个类型
验证器导入:flask_wtf.file   
flask_wtf.file.FileRequired 验证是否为空
flask_wtf.file.FileAllowed 验证上传文件后缀名

前台部分知识点:

项目结构

......
srccommonfooter  页脚alert    提示fade        动画gallary  画廊......store... vuex相关  pageshomecomponentsheader.vue......Home.vuedetailmesign......
......

1. flask_result 返回时,提供默认值
返回数据时,当axios 未返回渲染到页面时,使用变量出错。
**** 解决方法: 定义默认值 例如有使用book.owner.username , book.owner.avatar时,否则报错无定义,并无法显示。

      book: {owner: {......Object}},

2. vuex store一个Message,供于消息提醒
项目基本上每个页面都有操作结果的提醒,封装一个消息提醒的组件 alert.vue

 <div v-show="isshow" class="alertBox" :style="{background:this.$store.state.color}">{{mymessage}}</div>
......computed: {mymessage () {return this.$store.state.message}},watch: {mymessage (e) {this.isshow = true}}
  state: {message: '默认值',color: ''},mutations: {msgchange (state, res) {state.message = res.message    // color 自定义消息state.color = res.color  // color 自定义颜色setTimeout(() => {state.message = ''state.color = ''}, 3000)}}**** 重点:必须重置,否则下一次一样的消息将不显示组件写一个发送提醒消息的方法,方便多次调用
handleemit (message, color) {this.$store.commit('msgchange', {message: message, color: color})
}

3. 登陆注册:
利用 vue mounted 生命周期函数请求后端返回的csrf_token , 以及检验本地 localStorage,token是否过期。首次登陆成功返回存储token

 localStorage.setExpire('token', res.headers.token, 1000 * 60 * 60 * 24 * 2) // 设置两天过期注册发送email 激活账号

4 . 使用better-scroll 加载更多
swiper 盒子必须小于content高度才能滚动

可以滚动后,页面将不能点击,解决:****    
this.scroll = new BScroll(this.$refs.wrapper, {click: true,......
监听下拉方法,加载更多pullUpLoad: {// 当上拉距离超过盒子高度的的时候,就派发一个上拉加载的事件(触发条件)threshold: 0}
监听事件this.scroll.on('pullingUp', () => {axios.get('/api/booklist/?start=' + this.start).then(this.handleAxiosSuccess)})*** 对于下拉加载更多,双重遍历,遍历页码对应的数据
v-for="(p,index) in page" v-for="item in booklist[index]" :key="item.id"   //  booklist[index] 为第几次下拉的返回的数据

5. vue-awesome-swiper

图片点击事件
监听事件:on: {click: function (e) {window.open(e.target.src) // 跳转到网页}}使用:<swiper :options="swiperOption">  swiperOption为参数{ loop: true,effect: 'fade'......}<!-- slides --><swiper-slide v-for ='item of swiperList' :key="item.id"><img class="swiper-img" :src="item.url" alt=""> // 传递图片url</swiper-slide></swiper>画廊 组件关键参数:// observer启动动态检查器(OB/观众/观看者),当改变swiper的样式(例如隐藏/显示)或者修改swiper的子元素时,自动初始化swiper。// 默认falseobserver: true,observeParents: true

6. 过滤器,传递data中的值,并且使用v-html 显示

v-html="$options.filters.filemotion(comment.content,emotions)"  //       emotions: [] 是data中自定义的值
本过滤器是对,表情的插入表情标签的过滤 [赞]  [哈哈]  替换成 图片
方法:
emotions格式 :  filemotion (value, emotions) {value = value.replace(/(\[.+?\])/g, (e, e1) => {for (var i in emotions) {if ((emotions[i].value.indexOf(e1)) > -1) {return '<img src="' + emotions[i].icon + '">'}}})return value}

7. axios 更改请求头:

 axios.post('/api/comment/',参数, {headers: {'Content-Type': 'application/json'......}})

8. Proxytable设置跨域,进行数据交互

    proxyTable: {'/api': {target: 'http://127.0.0.1:5000',  //目标接口域名changeOrigin: true,  //是否跨域pathRewrite: {'^/api': '/v1/api/'   //重写接口}}}

9.router 模式
路由 mode="history"模式
当前端项目结合到flask 项目中,当vue 路由为history模式时,出现“刷新页面报错404”的问题

这是因为这是单页应用…其实是因为调用了history.pushState API 所以所有的跳转之类的操作
都是通过router来实现的,解决这个问题很简单,只需要在后台配置如果URL匹配不到任何静态资源

进入新页面,不回到页面顶部解决:

  scrollBehavior (to, from, savedPosition) {return { x: 0, y: 0 }},

转载于:https://www.cnblogs.com/donghaoblogs/p/10523983.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/264528.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac OS X Glut build instructions

Mac OS X Glut build instructions(在Mac上用glut库编写OpenGL程序) Wentao Sun, Autodesk, Inc. 1. Building GLUT apps under Mac OS X There are only a few modifications you need to make to the robot.c sample to get it compiled on your Mac. These instruction…

李战java_【阿里李战】解剖JavaScript中的 null 和 undefined

在JavaScript开发中&#xff0c;被人问到&#xff1a;null与undefined到底有啥区别&#xff1f;一时间不好回答&#xff0c;特别是undefined&#xff0c;因为这涉及到undefined的实现原理。于是&#xff0c;细想之后&#xff0c;写下本文&#xff0c;请各位大侠拍砖。总所周知&…

Android -- 获取摄像头帧数据解码

由于Android下摄像头预览数据只能 ImageFormat.NV21 格式的&#xff0c;所以解码时要经过一翻周折. Camera mCamera Camera.open();Camera.Parameters p mCamera.getParameters();p.setPreviewFormat(ImageFormat.NV21);/*这是唯一值&#xff0c;也可以不设置。有些同学可能…

跨域方法

1.jsonp,原理利用script的src属性(像img,iframe等有src属性的都支持跨域)引入js文件&#xff0c;并在引入成功后调用回调函数&#xff0c;数据通过参数的形式传过来。 例&#xff1a; 2.window.name 3.document.domain 4.h5的方法&#xff1a;window.postMessage 5.flash 6.COR…

C#发送Email邮件方法总结

通过.Net FrameWork 2.0下提供的“System.Net.Mail”可以轻松的实现&#xff0c;本文列举了3种途径来发送&#xff1a; 1.通过Localhost&#xff1b; 2.通过普通SMTP; 3.通过SSL的SMTP; 下面一个一个来说&#xff1a; 1.通过LocalHost 1public void SendMailLocalhost() 2 ...{…

java多线程之wait_(三)java多线程之wait notify notifyAll

引言今天我打算讲一下Object.wait,Object.notify,Object.notifyAll这三个方法. 首先我们查看一下api看看,官方api对这几个方法的介绍.理论Object.wait(): 导致当前线程一直等待,直到另一外一个线程用同一个对象调用Object.notify或Object.notifyAll方法.换种说法,就是调用Objec…

得不到和已失去

凉凉滑滑&#xff0c;这样的天气&#xff0c;我该喜欢的&#xff0c;就像在酷暑时所盼望的一样。可是又一次在凌晨凉飕飕的空气中醒来时&#xff0c;为什么我却倍感凄凉的蜷成一团怀念盛夏的热烈了呢。更加恶劣的是&#xff0c;为什么在正午炙热的阳光下&#xff0c;我却又在怀…

lightoj 1020 (博弈)

思路&#xff1a;很简单的博弈&#xff0c;找出每个人先拿的必胜态进行状态转移即可。#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int main(){int t, n, CASE(0);char …

2019 GDUT Rating Contest II : A. Taming the Herd

题面&#xff1a; A. Taming the Herd Input file: standard inputOutput file: standard outputTime limit: 1 secondMemory limit: 256 megabytesEarly in the morning, Farmer John woke up to the sound of splintering wood. It was the cows, and they were breaking out…

仅对此用户禁用 java_Spring Security实现禁止用户重复登陆的配置原理

这篇文章主要介绍了Spring Security实现禁止用户重复登陆的配置原理,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下系统使用了Spring Security做权限管理&#xff0c;现在对于系统的用户&#xff0c;需要改动配…

SQL server 系统优化--通过执行计划优化索引(1) (转)

SQL server 系统优化--通过执行计划优化索引&#xff08;1&#xff09; 前几天,远离上海&#xff0c;到了温州&#xff0c;在客户的这边处理系统慢&#xff0c;该系统每天正常down机7次左右&#xff0c;在线人员一多&#xff0c;系统运行缓慢&#xff0c;严重影响业务操作,到了…

Linux运维系统工程师系列---13

定制安装定制安装&#xff0c;也叫源码安装&#xff0c;需要自己编译源代码的安装方式步骤&#xff1a;1、解压源代码包2、配置 configure3、编译 make4、安装 make install接下来开始做实验&#xff0c;希望朋友们自己动手实践&#xff0c;有啥不清楚的可以直接提问我&#xf…

java system.setproperties_在JAVA中 System.getProperty 和 System.setProperty 方法.

今天着手研究TOMCAT源码.在刚開始的时候Startup类中init方法中调用非常多次System.getProperty和System.setProperty的方法.后来经过网上搜索才得知,这是对操作系统变量操作的方法.System还提供一个静态方法 System.getProperties(). 这种方法能够罗列出你系统的所有变量.调用S…

雷林鹏分享:XML 编码

XML 编码 XML 文档可以包含非 ASCII 字符&#xff0c;比如挪威语 &#xff0c;或者法语 。 为了避免错误&#xff0c;需要规定 XML 编码&#xff0c;或者将 XML 文件存为 Unicode。 XML 编码错误 如果您载入一个 XML 文档&#xff0c;您可以得到两个不同的错误&#xff0c;…

C#中理解接口以及接口的作用

在C#的开发中&#xff0c;接口是非常重要也非常好用的。可是很多时候很多人都不是很了解接口的做用&#xff0c;以及该如何使用。下面我们就来理解接口的作用&#xff0c;并看看如何使用吧。假设我们公司有两种程序员&#xff1a;VB程序员&#xff0c;指的是用VB写程序的程序员…

java开发中遇到的问题及解决方法(持续更新)

工作中&#xff0c;以C/C开发为主&#xff0c;难免与其他服务和Web进行交换&#xff0c;Java开发必不可少&#xff0c;又不想动用Eclipse大家伙&#xff0c;只能自己动手编写脚本进行Java代码的编译和运行&#xff0c;期间遇到的一些问题&#xff0c;记录下来供自己和大家参考。…

c语言转化java工具_详解C语言常用的一些转换工具函数

1、字符串转十六进制代码实现&#xff1a;void StrToHex(char *pbDest, char *pbSrc, int nLen){char h1,h2;char s1,s2;int i;for (i0; i{h1 pbSrc[2*i];h2 pbSrc[2*i1];s1 toupper(h1) - 0x30; //toupper 转换为大写字母if (s1 > 9)s1 - 7;s2 toupper(h2) - 0x30;if (…

vue项目使用eslint

转载自 https://www.cnblogs.com/hahazexia/p/6393212.html eslint配置方式有两种&#xff1a; 注释配置&#xff1a;使用js注释来直接嵌入ESLint配置信息到一个文件里配置文件&#xff1a;使用一个js&#xff0c;JSON或者YAML文件来给整个目录和它的子目录指定配置信息。这些配…

提里奥·弗丁(魔兽世界里的NPC)

弗丁的名字大家也许并不熟悉&#xff1b;但白银之手骑士团的大名&#xff0c;恐怕天下无人不识。作为白银之手骑士团创始人光明使者乌瑟尔的亲密友人&#xff0c;当年的弗丁是骑士团中地位最为崇高的圣骑士之一。在第二次战争中身先士卒的表现无愧白银之手的神圣之名。荣归故里…

java http请求插件_java http请求工具整理

处理了http 的get和post的请求&#xff0c;分别支持同步处理&#xff0c;异步处理两种方式下见代码。Slf4jpublic class HttpUtils { /** * 同步请求http请求 不推荐 * * param url * return */ public static byte[] httpGetSync(String url) { HttpGet httpGet new HttpGet(…