heroku
I really enjoy making stuff, but I really hate deployment. I have a bunch of ideas that sit on my local machine and just gather dust since I cannot be bothered to deploy them for the world to see. In the past, I kept trying to set up my own server from scratch. This included installing all of the linux packages, dealing with nginx configs and just all of the server management stuff I really don’t have a taste for. For some reason in my development life, I never heard of Heroku. Heroku is perfect for what I need. It basically allows you to connect up a git repository and when you push it to their remote it automatically figures out what you are running (detects flask or node.js etc) and does the build all by itself. Literally just pushing code to production with no server side headaches.
我真的很喜欢制作东西,但是我真的很讨厌部署。 我有很多想法,它们坐在我的本地计算机上,只是积dust灰尘,因为我不愿意将它们部署给全世界。 过去,我一直尝试从头开始设置自己的服务器。 这包括安装所有linux软件包,处理nginx配置以及我真正不喜欢的所有服务器管理内容。 由于开发生活中的某些原因,我从未听说过Heroku。 Heroku非常适合我的需求。 它基本上允许您连接git存储库,并将其推送到其远程目录时,它会自动找出您正在运行的内容(检测flask或node.js等)并自行完成所有构建。 从字面上看,只是将代码推向生产环境而已,没有服务器方面的麻烦。
To commemorate my new found best friend I wanted to show how to build a simple ReactJs + Flask framework that I will use as my template for developing APIs and Web Applications going forward. The idea here is to make something reusable so I can just clone the repo and get to work on something new without redoing any steps.
为了纪念我新发现的最好的朋友,我想展示如何构建一个简单的ReactJs + Flask框架,该框架将用作我今后开发API和Web应用程序的模板。 这里的想法是使某些东西可重用,这样我就可以克隆存储库并开始处理新的东西而无需重做任何步骤。
设置Heroku (Setting up Heroku)
For this all you have to do is go to www.heroku.com and sign up for an account. Once your all good to go and logged in you should see a screen like this which shows your current apps:
为此,您要做的就是访问www.heroku.com并注册一个帐户。 一切顺利并登录后,您应该会看到一个类似这样的屏幕,其中显示了您当前的应用程序:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/d04ce53a6a85e47e57d87b13761b623d.png)
Then all you do is hit the New button on the top right and create your own new app! Yes that is literally it.
然后,您要做的就是点击右上角的“新建”按钮并创建自己的新应用! 是的,从字面上看就是这样。
From what I can tell it basically set up a git repository for us on their server and it is tied to our user account. This means we can now push code to this app on heroku. The question is how to do this? This is where you have to download the Heroku CLI (Command Line Interface). This allows us to run command line commands to login and push code etc. The CLI can be download here:
据我所知,基本上是在他们的服务器上为我们建立了一个git存储库,它与我们的用户帐户绑定在一起。 这意味着我们现在可以将代码推送到heroku上的该应用程序。 问题是如何做到这一点? 您必须在这里下载Heroku CLI(命令行界面)。 这使我们可以运行命令行命令来登录和推送代码等。可在此处下载CLI:
Just make sure to download it for your system. Once installed you can open a terminal and run heroku login which should open a web browser for you to log into your account.
只要确保为您的系统下载它即可。 安装完成后,您可以打开一个终端并运行heroku登录,这将打开一个Web浏览器供您登录帐户。
其他软件 (Other Software)
There are a few other pieces of software you will need. I'm not going to go into detail about how to install them but I’ll list them out here.
您还需要其他一些软件。 我不会详细介绍如何安装它们,但我会在这里列出它们。
- Git: This is a repository management system Git:这是一个存储库管理系统
- Python: This is of course Python. I would recommend 3.7.x as this is what I am using! Python:当然是Python。 我建议使用3.7.x,因为这是我正在使用的!
- NodeJS/NPM: Used for the ReactJS development part NodeJS / NPM:用于ReactJS开发部分
本地设置(Local Setup)
Now that all of the software is installed we will set up our directory and start making our API and client front end interface. First we want to make a new directory (NB: I am using datastuffplus for the name of all my things):
现在已经安装了所有软件,我们将建立目录并开始制作API和客户端前端接口。 首先,我们要建立一个新目录(注意:我使用datastuffplus作为我所有东西的名称):
mkdir datastuffplus
cd datastuffplus
git init <--- This makes the current folder into a repo# Links the repo to our heroku project!
heroku git:remote -a datastuffplus
At this point all we have done is made a directory that is linked up to our Heroku project repository. This means that when we add code and commit/push it goes to Heroku and self deploys. Next we can build a simple API using Flask.
至此,我们所要做的就是创建一个目录,该目录链接到我们的Heroku项目存储库。 这意味着,当我们添加代码并提交/推送时,它将转到Heroku并自行部署。 接下来,我们可以使用Flask构建一个简单的API。
构建Flask API和Web服务器 (Building the Flask API and Web Server)
Our flask server will be doing two major things. The first is to serve the web files that make our final webpage (front end). The second is to act as the API service to do some python specific tasks and send the results back to the front end website.
我们的Flask服务器将做两件事。 首先是提供构成最终网页(前端)的网络文件。 第二种是充当API服务来执行一些特定于python的任务,并将结果发送回前端网站。
Start with generating a virtual environment for our python install. This allows us to isolate this environment from our system. Especially useful if you need to install certain versions of packages on this project but different versions on another.
首先为我们的python安装生成虚拟环境。 这使我们能够将此环境与系统隔离。 如果您需要在此项目上安装某些版本的软件包,而在另一个项目上安装不同版本的软件包,则特别有用。
python -m venv venv/
To use this environment we need to activate it. Depending on your OS it may look a bit different but on Windows we run:
要使用此环境,我们需要激活它。 根据您的操作系统,看起来可能有些不同,但是在Windows上我们运行:
cd ./venv/Scripts/
activate.bat
Next we install our python packages and get it ready for deploying to Heroku. Note that since we are in our active venv the packages are only installed in this isolated directory. Perfecto.
接下来,我们安装python软件包,并准备将其部署到Heroku。 请注意,由于我们位于活动的venv中,因此软件包仅安装在此隔离的目录中。 完美
pip install flask flask-cors gunicorn boto3 matplotlib
The above python packages are for the following:
上面的python包用于以下用途:
flask: The main server functionality
flask :主要服务器功能
flask-cors: Used for cross-origin requests. Basically lets you call the endpoints from a different system without violating security
flask-cors :用于跨域请求。 基本上,您可以从其他系统调用端点,而不会破坏安全性
gunicorn: It is a production server package that in this case is used by Heroku to serve up the site
gunicorn :这是生产服务器程序包,在这种情况下,Heroku使用它来提供站点服务
boto3: This package is used to access Amazons S3 buckets (think of this as a cloud based directory to store files) NB: Since Heroku does not guarantee persistence of files after it spins down it is super important to use this kind of cloud storage
boto3 :此软件包用于访问Amazon S3存储桶(将其视为存储文件的基于云的目录) NB :由于Heroku不能保证其在旋转后仍保持文件的持久性,因此使用这种云存储非常重要
matplotlib: A package used to make plots. This only really matters since our test API will be using it to generate a pie chart
matplotlib :用于制作绘图的软件包。 这真的很重要,因为我们的测试API将使用它来生成饼图
A few more steps before we actually code our server. In order to keep track of all the required packages, Heroku needs a requirements.txt file which basically lists out all of the python packages we have installed. To make it we just run:
在实际编码服务器之前,需要执行一些其他步骤。 为了跟踪所有必需的软件包,Heroku需要一个requirements.txt文件,该文件基本上列出了我们已安装的所有python软件包。 为此,我们运行:
python freeze > requirements.txt
饼图API (Pie Chart API)
So what do we want to actually create? One thing I wanted was a nice high resolution pie chart for some graphics I make. I generally have done this using python matplotlib, but it is kinda annoying if I need to actually run python each time. So let’s make it into a service to make my life easier, and also other people can use it! Bonus!
那么我们要实际创建什么? 我想要的一件事是为我制作的某些图形制作一个漂亮的高分辨率饼图。 我通常使用python matplotlib完成此操作,但是如果我每次都需要实际运行python,这有点烦人。 因此,让它成为一项服务,使我的生活更轻松,其他人也可以使用它! 奖金!
The first step is to always just define our function that does the work. Below I have pasted the function that will make the pie chart and save it locally:
第一步是始终只定义完成工作的函数。 下面,我粘贴了将创建饼图并将其保存在本地的函数:
def GeneratePie():
# Get the input data (Wedge is the distance between slices) data = [60,40]
colors = ['#003049','#ffcdb2']
wedge = 0.05 # Make a matplotlib (high res) pie chart! fig1, ax1 = plt.subplots(figsize=(20,20))
patches, texts = ax1.pie(data,explode=[float(wedge) for w in
range(0,len(data))], colors = colors, startangle=90) # Equal aspect ratio ensures that pie is drawn as a circle ax1.axis('equal')
plt.tight_layout() # Save the image temporary on the local machine plt.savefig(os.getcwd() + '/test.png');
And the output looks like this:
输出看起来像这样:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/a8e06c87a6b6542ac6a1f0fb7f5f0bcd.png)
So we now have our function that will do what we want. The next step is to wrap it in our flask server.
因此,我们现在有了可以完成我们想要的功能。 下一步是将其包装在烧瓶服务器中。
In your working directory make a new python file called app.py. The bare bones looks like this (we will fill it in later):
在您的工作目录中,创建一个名为app.py的新python文件。 裸露的骨骼看起来像这样(稍后我们将进行填充):
The first things we do is import the packages we need to run
我们要做的第一件事是导入我们需要运行的软件包
from flask import Flask,
render_template,send_from_directory,request, jsonify,
make_response
from flask_cors import CORS, cross_origin
import boto3
import os
Next we will define the flask app object and set the static folder and URL:
接下来,我们将定义flask应用程序对象并设置静态文件夹和URL:
app = Flask(__name__
,static_folder='client/build',static_url_path='')
cors = CORS(app)
In the above, the static folder and url are important when we want to also server the front end website (to come later in this article). The static_folder will point to the built version of our ReactJS front end and the static_url_path needs to be set or else that build will have references to all the wrong places. ie. the paths to CSS files are going to be relative to the location and if you do not specify this they cannot be found!
在上面,当我们还要服务器前端网站时,静态文件夹和url很重要(将在本文后面介绍)。 static_folder将指向我们的ReactJS前端的构建版本,并且需要设置static_url_path ,否则该构建将引用所有错误的位置。 即。 CSS文件的路径将相对于该位置,如果您未指定此路径,则找不到它们!
@app.route('/api')
@cross_origin()
def Welcome():
return "Welcome to the API!!!"@app.route('/api/justpie/')
@cross_origin()
def GeneratePie():
....@app.route('/')
def serve():
return send_from_directory(app.static_folder, 'index.html')if __name__ == '__main__':
app.run(host='0.0.0.0')
In the above skeleton code we see three new routes for our server. These act as the endpoints that you can call via a web browser.
在上面的框架代码中,我们为服务器看到了三个新路由。 这些充当您可以通过Web浏览器调用的端点。
@app.route('/api'): This is the route that will act as the base of our API calls. All it does right now is send back a cheery little message!
@app .route('/ api'):这是将作为我们API调用基础的路由。 现在所做的只是发送回愉快的小消息!
@app.route(‘/api/justpie’): The bulk of the work is done with this endpoint. This is where we will call the pie chart generation function from before (with some modifications to get it taking in user inputs via GET requests and storing the final image on an S3 bucket)
@app .route('/ api / justpie'):大部分工作都是通过此端点完成的。 这是我们从前调用饼图生成函数的地方(经过一些修改,使其通过GET请求接收用户输入并将最终图像存储在S3存储桶中)
@app.route(‘/’): This root endpoint is going to point to the built version of the ReactJS code where we will call the endpoints and show the results in a web browser.
@app .route('/'):此根端点将指向ReactJS代码的构建版本,在此我们将调用这些端点并在Web浏览器中显示结果。
Now that the skeleton is set up we need to look at how to modify our stand alone python function into a flask callable function.
现在已经建立了骨架,我们需要研究如何将独立的python函数修改为flask可调用函数。
修改功能 (Modifying the Function)
There are two main changes to make to the GeneratePie() function above.
上面的GeneratePie()函数有两个主要更改。
- We need to take in inputs from the client via a GET request 我们需要通过GET请求从客户端获取输入
- Storing the final file onto the Amazon S3 bucket so it persists across Heroku reboots将最终文件存储到Amazon S3存储桶中,以使其在Heroku重启后仍然存在
To make the first modification we replace the following code
为了进行第一次修改,我们替换以下代码
data = [60,40]
colors = ['#003049','#ffcdb2']
wedge = 0.05
with
与
# Get the input data from the request
data = request.args.get('data')
colors = request.args.get('colors')
wedge = request.args.get('wedge')# Turn it into a list
data = [float(i) for i in data.split(',')]
colors = ['#'+i for i in colors.split(',')] <-- Adding # to string
The way the data gets passed is via the web URL. For example to mimic what was done in the original function you could call the API as:
数据的传递方式是通过Web URL。 例如,要模仿原始函数中的操作,可以将API调用为:
http://localhost:5000/api/justpie/?data=10,10,80&colors=003049,ffcdb2,0fc9b2&wedge=0.02
http:// localhost:5000 / api / justpie /?data = 10,10,80&colors = 003049,ffcdb2,0fc9b2&wedge = 0.02
You can see how we are passing in the parameters.
您可以看到我们如何传递参数。
NB: The colour is not using the hashtag since it is a special character, so we just add this in when turning it into a list (shown in the modification above)
注意:由于颜色是特殊字符,因此未使用主题标签,因此我们仅在将其转换为列表时将其添加(如上面的修改所示)
The second change is to replace the code:
第二个更改是替换代码:
# Save the image temporary on the local machineplt.savefig(os.getcwd() + '/test.png');
with
与
# Save the image temporary on the local machine
plt.savefig(os.getcwd() + '/test.png');# Connect to the S3 bucket and just drop it on there
s3 = boto3.client('s3', aws_access_key_id=ACCESS_KEY,
aws_secret_access_key=SECRET_KEY)
s3.upload_file(os.getcwd() +
'/test.png',bucket,'test.png',ExtraArgs={'ACL':'public-read'})# The return will be a json where message contains the image path (URL)
status = {};
status['status'] = 'DONE';
status['message'] = 'https://'+bucket+'.s3.ca-central-1.amazonaws.com/test.png'return make_response(jsonify(status), 200)
In the above there are a few things to look at:
上面有几件事要看:
- We still save the file locally, but we then connect to the S3 bucket to upload the file 我们仍然将文件保存在本地,但随后我们连接到S3存储桶以上传文件
- The ACCESS_KEY and SECRET_KEY come from your own Amazon account. I will not go into detail on how to set that up because there are a million articles on it and it is pretty seamless! ExtraArgs={‘ACL’:’public-read’} is used to make the file public. ACCESS_KEY和SECRET_KEY来自您自己的Amazon帐户。 我不会详细介绍如何设置它,因为上面有100万篇文章,而且非常无缝! ExtraArgs = {'ACL':'public-read'}用于使文件公开。
- Lastly you can see we are sending back a json response that gives the upload location URL on our public S3 bucket. This can be used by the front end to display the results to the user. 最后,您可以看到我们正在发送回json响应,该响应给出了公共S3存储桶上的上传位置URL。 前端可以使用它来向用户显示结果。
So at this point our API is ready to go! Now all we have to do is get a front end website working to show it off!
因此,此时我们的API已准备就绪! 现在,我们要做的就是让一个前端网站进行展示!
带有CoreUI的ReactJS前端 (ReactJS Frontend with CoreUI)
For the front end I am using ReactJS in order to make a simple dashboard and interact with the API. I am not going to go into great detail of the dashboard styling itself but will touch on how it interacts with the API. The template I am using is from
对于前端,我使用ReactJS来制作一个简单的仪表板并与API进行交互。 我将不对仪表板样式本身进行详细介绍,但会涉及其如何与API交互。 我正在使用的模板来自
It is a wonderful free admin dashboard available in react and many other frameworks. I just downloaded it and extracted the zip file. As long as you have npm installed you can just run the install to get the required packages and then spin it up with
这是一个很棒的免费管理仪表板,可用于react和许多其他框架。 我刚下载并解压缩了zip文件。 只要安装了npm ,就可以运行安装程序以获取所需的软件包,然后使用
mkdir client
cd ./client/
npm install
npm start
All of the files I decided to place in a client/ sub-directory next to the app.py.
我决定将所有文件放在app.py旁边的client /子目录中。
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/da83cf74764477049c84d68c798c48a0.png)
The ReactJS web portion that actually calls and displays the results is shown here:
这里显示了实际调用并显示结果的ReactJS Web部分:
# Define the function (functional components not classes)
const JustPie = () => { # Set up the state variables
const [downloadLink, setDownloadLink] = useState(""); # Image # Default settings for our form
const [data, setData] = useState("40,60");
const [colors, setColors] = useState("003049,ffcdb2")
const [wedge, setWedge] = useState(0.05); # NB: This URL will changed depending on your release!!!
const api_base_url =
'http://datastuffplus.herokuapp.com/api/justpie/' # Function to fetch the data from our API
function fetchData(){ # Set the image to be empty setDownloadLink(''); # Build up the endpoint to our API
var url_req_string = api_base_url+ "?data=" + data + "&colors="
+ colors + "&wedge=" + wedge; # Fetch the URL and parse the JSON response
fetch(url_req_string)
.then(res => res.json())
.then(
(result) => { # Set the image to be the API return "message"
setDownloadLink(result.message);
}, (error) => {
console.log(error); }
);
};# The rest of the code that runs the actual render
return (<> </>)
The above simply calls a fetch to our API and updates the state of the download link which is the S3 bucket image URL.
上面的代码简单地调用了我们的API的fetch并更新了下载链接(即S3存储桶图片URL)的状态。
Finally just for the sake of completeness the next section which appears in the rendering of the page shows how the state variables connect to the forms:
最后,为了完整起见,出现在页面呈现中的下一部分显示了状态变量如何连接到表单:
# Update the data when the form changes
<CInput type="text" id="hf-text" name="hf-text" placeholder="40,60" autoComplete=""
value={data}
onChange={(event)=> setData(event.target.value)}/># Call the API on a button press<CButton type="submit" size="sm" color="primary"
onClick={() => fetchData()}>
That’s it! You can check how it looks by running:
而已! 您可以通过运行以下命令检查外观:
npm start
My local setup looks like this:
我的本地设置如下所示:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/cc5f72cb4cbdcc0b5b27d1a668cf23a2.png)
As you can see we have the input forms as well as a section with the output results! Now this is all running locally the final step is to deploy this to Heroku.
如您所见,我们有输入表单以及带有输出结果的部分! 现在这一切都在本地运行,最后一步是将其部署到Heroku。
部署到Heroku (Deploying to Heroku)
There are a few last steps to get everything ready to go for deployment. We will need to set up a Procfile for our server and do a build of the React code so our flask server can just send over the result.
最后有几个步骤可以使一切准备好进行部署。 我们将需要为服务器设置一个Procfile并构建React代码,以便我们的flask服务器可以发送结果。
程序文件 (Procfile)
All you have to do is make a new file called Procfile and fill the content with:
您要做的就是创建一个名为Procfile的新文件,并用以下内容填充内容:
web: gunicorn app:app
React构建 (React Build)
Another simple step, once you are in the /client/ directory you can run:
另一个简单的步骤,一旦进入/ client /目录,就可以运行:
npm run build
This will generate a new directory called /client/build/ which is where our Flask server is pointing to on the root route.
这将生成一个名为/ client / build /的新目录,这是我们的Flask服务器在根路由上指向的目录。
NB: The build step can take some time depending on how big your application is
注意:根据您的应用程序的大小,构建步骤可能需要一些时间
Finally we can add all of the files to our git repository as follows:
最后,我们可以将所有文件添加到git存储库中,如下所示:
git add .
git commit -am "All of teh codes"
git push heroku master
Now this will also take a lot of time so go get a coffee. Once the push is complete you will see Heroku automatically detect that you are pushing in a Flask application and it will do all installations of packages and servers for your! This is crazy if you have ever tried to do it yourself!
现在,这也将花费很多时间,所以去喝杯咖啡吧。 推送完成后,您将看到Heroku自动检测到您正在推送Flask应用程序,它将为您完成软件包和服务器的所有安装! 如果您自己尝试过,那就太疯狂了!
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/aa26d9abb7c8c07ffd55b7144227151d.png)
After all of that hard work we can see what we have created and can share it with the masses. Check out this video of what it looks like in action!
经过所有这些艰苦的工作,我们可以看到我们创建的内容并可以与大众分享。 观看此视频,了解实际情况!
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/be6832275ff2e76d20dfbee3be013284.png)
Finally here is the link where you can try it yourself!
最后,这里是您可以自己尝试的链接!
If you have questions or need someone to consult on your project please send me a message at kyleanthonypastor@gmail.com and if you are on instagram please follow me @datastuffplus.
如果您有问题或需要某人咨询您的项目,请给我发消息kyleanthonypastor@gmail.com;如果您在instagram上,请关注我@datastuffplus。
翻译自: https://towardsdatascience.com/reactjs-python-flask-on-heroku-2a308272886a
heroku