.input{width:200px;}button{width:100px;}.textarea{width:900px;}Web开发中前后端分离已经是家常便饭,但是很多初学者并不熟悉如何进行前后端分离和后端,他们在构建演示时遇到了很多问题。今天分享一下如何使用Vue和Django快速搭建前后端分离的项目。先搭建前端,这里使用Vue3,可以参考官方文档[1]。在终端或命令窗口执行:npminitvue@latest这会自动安装最新版本的Vue,并初始化一个Vue项目,填写一个项目名称,回车处理默认值:然后执行这些,就可以了你会看到前端项目已经启动:cdfront_endnpminstallnpmrundev安装依赖于当前的前端项目,只会显示一个静态网页。我们需要给它添加一些材料,比如一个表单,让它发起一个get或者post请求,这样我们就需要在front_end目录下安装并执行以下依赖:npmielement-plus-Snpmiaxios-Snpmimockjs-S如果你使用的是Vue2,请安装element-ui。其中:element-plus/element-ui是vue的一个ui库。主要介绍使用一些好看的按钮、表单、文本框等,可以替换也可以不替换自己喜欢的ui库。axios类似于AJAX的功能,主要是访问后端API获取数据。mockjs主要用来模拟后台api接口返回的数据。当前端工程师需要独立于后端并行开发时,后端接口还没有开发出来,那么前端如何获取数据呢?这时候可以考虑前端自己模拟假数据,利用mockjs生成随机数据,拦截Ajax请求。导入依赖下面我们修改main.js,全局引入element,使用mockjs模拟界面数据-plus/dist/index.css'import'./assets/main.css'import'./mock'constapp=createApp(App)app.use(ElementPlus)app.mount('#app')这里,那里是一个mock.js,我们还没写,以后再写。在front_end/src/components/下写一个Demo页面,写一个TestApi.vue文件,内容如下:获取所有查询postsubmit.input{width:200px;}button{width:100px;}.textarea{width:900px;}上面的页面有一个form,可以发起getorpostrequest这个组件就完成了,需要在页面上展示,只需要修改App.vue,将TheWelcome全部替换成TestApi即可。现在你可以编写mock.js了。在front_end目录下新建mock.js文件,写入如下内容://introducemockjsimportMockfrom'mockjs'//获取mock.Random对象constRandom=Mock.Random;//使用mockjs模拟数据Mock.mock('api/users/',(req,res)=>{//向/api/users/路由发送或获取请求时,Mock会拦截请求并返回上述数据varlist=[{"url":“http://127.0.0.1:8000/users/3.json”,“用户名”:“aaaaaa”,“电子邮件”:“”,“组”:[]},{“url”:“http://127.0.0.1:8000/users/2.json","username":"somenzz","email":"","groups":[]},{"url":"http://127.0.0.1:8000/users/1.json","username":"admin","email":"admin@example.com","groups":[]}]returnlist})现在,再次运行npmrundev,在浏览器中打开“http://127.0.0.1:5173/”,点击get按钮,会发现mock已经生效。前端demo就差不多了。接下来让我们看看后端工程师的任务。然后构建后端。这里我们以DRF(DjangoRESTFramework)为例。如果你还是第一次接触DRF,建议先看官方教程[2]。执行以下命令创建后台Demo:django-adminstartprojectrear_endcdrear_enddjango-adminstartapprestapi#这一步会创建一个管理员用户,请记录设置密码pythonmanage.pycreatesuperuser--emailadmin@example.com--usernameadmin接下来在settings.py文件中的INSTALLED_APPS列表中添加'rest_framework',然后执行以下命令启动django后端服务。pythonmanage.pyrunserver我们在浏览器中输入http://127.0.0.1:8000/admin,然后输入管理员用户名和密码,新增3个用户,可以随意填写,目的是添加一个更多的测试数据。接下来访问http://127.0.0.1:8000/user.json可以看到返回的数据是如下json格式。后端开发工作告一段落。在前后端联调测试开发环境中,vue会占用一个端口,这里是localhost:5173,djangorestframework也会占用一个端口,比如localhost:8000,那么localhost:5137需要获取数据localhost:8000的联调,所以我们把前端demo中RestApi.vue中请求的接口从api/users改成了http://127.0.0.1:8000/users.json。在实际开发中,配置文件就是用来解决这个替换问题的。在实际执行过程中,get请求错误的结果如下:AccesstoXMLHttpRequestat'http://127.0.0.1:8000/users.json'fromorigin'http://localhost:5137'hasbeenblockedbyCORS策略:请求的资源上不存在“Access-Control-Allow-Origin”标头。在这里翻译成中文,跨源资源共享(CORS)策略阻止从localhost:5137到127.0.0.1:8000的访问。那么什么是跨域资源共享,这里解释一下:跨域资源共享的目的是共享,允许浏览器向跨域服务器发送XMLHttpRequest请求,从而克服AJAX只能在同源。很明显localhost:5137到localhost:8000是不同来源的,所以这里采用了跨域资源共享策略。但是CORS需要浏览器和服务器的支持。目前所有浏览器都支持该功能,IE浏览器不能低于IE10。整个CORS通信过程由浏览器自动完成,无需用户参与。对于开发者来说,CORS通信和同源AJAX通信没有区别,代码完全一样。浏览器一旦发现AJAX请求是跨域的,就会自动添加一些额外的header信息,有时会多出一个请求,但用户感觉不到。因此,实现CORS通信的关键是服务器。只要服务端实现了CORS接口,就可以实现跨域通信。那么解决这个问题有两种方法:第一种:设置服务器允许localhost:5137跨域访问,上线后再改回来。为什么要改回来,因为要避免跨域攻击,详见知乎https://www.zhihu.com/question/26379635[3]。方法二:将127.0.0.1:8000返回的json数据复制到mock中进行联调。好像第二种更方便,前提是你需要学习如何使用mock来模拟后端api。为了在开发环境中联合调试,我们将第一种方法进行到底,现在修改django配置文件settings.py允许跨域。1.安装django-cors-headerspipinstalldjango-cors-headers2。修改settings.pyINSTALLED_APPS=[......'corsheaders',......]MIDDLEWARE=[......'corsheaders.middleware.CorsMiddleware','django.middleware.common.CommonMiddleware',......]CORS_ORIGIN_ALLOW_ALL=TrueCORS_ALLOW_CREDENTIALS=True至此,get请求执行成功。在这里,我们填写用户名和电子邮件地址。提交post请求后,users表中会增加一条新记录,也可以通过get请求查询。你可以自己试试。在实际开发中,我们请求后端接口时的url一般不会填写ip地址和端口,而是填写'api/xxx'的形式,写在这里是为了展示如何进行前后端-以开发环境形式结束联调。线上部署先执行npmrunbuild打包。默认配置下会生成一个dist目录,dist目录下会生成一个index.html文件,还有静态资源js、css、fonts,都在dist目录下。这个dist目录就是我们需要在线部署的资源。在网上搜索了一下,主流的方法有两种,一种是直接在nginx上配置dist目录的位置,然后用nginx反向代理UWSGI或者gunicorn,一般使用socket协议。另一种是django驱动dist目录下的资源,这样不涉及跨域问题,只是打包的时候需要稍作调整。在front_end目录下新建vue.config.js文件,添加如下内容:module.exports={//options...assetsDir:'static'}再次执行npmrunbuild,我们会发现js,css,和字体都放在之所以这样是因为django模板视图指定的html文件不能和静态资源放在同一个路径下,至少需要一个相对目录。也就是说,django配置文件中的STATIC_URL默认为'/static/',不允许为空,即127.0.0.1:8000/static/js/xxx.js可以正确访问静态资源,但是默认的vue默认配置生成的静态资源是和index.html同级的,所以需要稍微调整一下。接下来修改django的配置文件:1.可以把所有关于跨域的代码都注释掉。参照前面第2步,添加如下配置,使django在调试模式下可以找到静态资源STATICFILES_DIRS=[os.path.join(BASE_DIR,"dist/static")]TEMPLATES=[{'BACKEND':'django模板上下文处理器。debug','django.template.context_processors.request','django.contrib.auth.context_processors.auth','django.contrib.messages.context_processors.messages',],},},]修改setting.py同目录添加urls.py模板视图,指定index.htmlurlpatterns=[path('admin/',admin.site.urls),path('',TemplateView.as_view(template_name="index.html"),name='index'),path('',include(router.urls)),path('api-auth/',include('rest_framework.urls',namespace='rest_framework'))]执行pythonmanage.py后打开浏览器runserver服务器,执行get请求,可以看到如下结果。此时前后端同源。下面的配置与第一种方案基本相同。设置django收集静态资源的路径STATIC_ROOT,执行pythonmanage.pycollectstatic,然后参考下面的uwsgi配置进行生产环境部署。这种方式不需要后台允许跨源,比较安全。生产环境上线,需要了解nginx和uwsgi。nginx可以指定首页index.html、静态资源、端口转发、路由转发、负载均衡等,网上有详细的配置说明,这里就不一一列举了。uwsgi也可以指定静态资源,主要用来驱动django。这是我使用的配置:[uwsgi]socket=:80master=truechdir=/home/aaron/web/django-mysitewsgi-file=blogproject/wsgi.pyprocesses=4threads=10virtualenv=/home/aaron/pyenvstatic-map=/static=/home/aaron/web/django-mysite/staticstatic-map=/media=/home/aaron/web/django-mysite/mediamime-file=/home/aaron/web/django-mysite/mime.typesdisable-logginglogto=/home/aaron/web/django-mysite/uwsgi.log#让进程在后台运行,并记录到指定的日志文件或udpserverdaemonize=/home/aaron/web/django-mysite/uwsgi.log参考资料[1]官方文档:https://vuejs.org/guide/quick-start.html#with-build-tools[2]官方教程:https://www.django-rest-framework.org/tutorial/quickstart/[3]https://www.zhihu.com/question/26379635:https://www.zhihu.com/question/26379635