如何将HerokuPostgres与我的flask-sqlalchemy应用程序一起使用?
现在我有一个应用程序可以将用户的数据写入名为 users.sql 的数据库文件。但是,我通过github将其推送到heroku,并且数据不粘。如果过了一段时间,heroku 将休眠,并且在检测到另一个登录时必须重新部署所有文件。我听说我可以将 heroku postgres 添加为 heroku 的插件,但我不确定如何将其与我当前的代码集成。我该怎么做才能设置它?
回答
我在尝试将我的应用程序连接到 Postgres 时偶然发现了您的问题,但由于缺乏明确的说明而感到非常沮丧。所以这是我努力解决的所有错误的分步过程(因为那是教程让您在不知不觉中打雷时喘不过气来的地方......)
TL; 博士
- 安装 Postgres
- 安装 Heroku CLI
- 安装 psycopg2 或 psycopg2-binary 和 gunicorn
- 使用 Postgres 数据库在 Heroku 中创建一个应用程序并将数据库 url 保存为
SQLALCHEMY_DATABASE_URI - 创建 Procfile、requirements.txt 和 runtime.txt
- 推送到 Github 并将 repo 连接到 Heroku
- 部署分支
from app import dbdb.create_all()
我使用 WSL,所以我的答案中的所有命令行语法都是 Bash,我正在使用 Windows 10。
我工作的一部分以YouTube教程由Traversy媒体。这是他使用的Github 存储库(我绝对建议最初使用基本应用程序,而不是在带有额外包的复杂应用程序中遇到错误时苦苦挣扎)。
在你开始之前
- 在 Heroku 中创建一个帐户并安装 Heroku CLI
- 下载并安装 PostgreSQL(这也将为您提供 pgAdmin 4)
- Fork 并克隆Github 存储库,并检查它是否运行正常(如果您不使用自己的应用程序)
预赛
- 创建一个虚拟环境并安装所有软件包。确保您拥有
psycopg2和gunicorn
ERROR: Failed building wheel for psycopg2-binary无论出于何种原因,psycopg 都拒绝在我的系统上安装。您可以通过使用
pip3 install psycopg2-binary来解决这个问题- 就我们的要求而言,没有区别。
连接到 Postgres
从开始菜单打开 pgAdmin 4。如果这是您第一次登录或已注销,这可能会提示您输入密码。
could not connect to server: Connection refused (0x0000274D/10061) Is the server running on host "127.0.0.1" and accepting TCP/IP connections on port 5432?使用
sudo service postgresql status检查PostgreSQL服务器正在运行。如果是,请尝试停止并启动它。如果不是,请启动它。
sudo service postgresql start
sudo service postgresql stop
在左侧面板中,右键单击Databases并单击 Create > Database...。输入您的数据库名称(本教程使用“lexus”)并保存。
在app.py(或您进行数据库配置的任何地方)中找到该行
if ENV == 'dev':
...
app.config['SQLALCHEMY_DATABASE_URI'] = ''
并将数据库连接字符串放在引号内。语法是
postgresql://[username]:[password]@[host name]/[db name]
# [username] - Right-click on your server in pgAdmin (probably a variation of `PostgreSQL 13`). Go to the Connection tab and check the Username field.
# [password] - The root password you set the first time you logged in to pgAdmin.
# [host name] - In the same place as your username, in the Host name/address field.
# [db name] - The name you entered when creating your database.
就我而言,连接字符串是:
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:123456@localhost/lexus'
进入python控制台并创建数据库:
>>> from app import db
>>> db.create_all()
如果您在这方面没有出错,请认为自己是切片面包以来最幸运的事情。在 pgAdmin 中,转到 Databases > [your db name] > Schemas > Tables 以检查它们是否已创建。
ImportError: cannot import name 'db' from 'app' (unknown location)
db不在app您的应用程序中。找到它的定义位置并从那里导入。
(psycopg2.OperationalError) FATAL: password authentication failed for user "postgres"您使用了错误的密码。我发现这很令人困惑,因为不清楚您是需要使用主密码(第一次登录 pgAdmin 时设置的密码)还是要连接的数据库的密码。这是这里需要的主密码。在命令行中输入
psql -h 127.0.0.1 postgres(psql -h [ip address] [username]) - 验证密码是连接字符串所需的密码。
(psycopg2.OperationalError) FATAL: database "lexus" does not exist您可能连接到错误的数据库、使用了错误的用户名,或者您的数据库尚未创建。检查您的连接字符串和 pgAdmin 以确认详细信息正确无误。
db.create_all() seemed to work, but I have no tables in pgAdmin!如果您的数据库模型存储在单独的文件中,请
app.py在db初始化后将它们导入。它应该是这样的:app = Flask(__name__) ... db = SQLAlchemy(app) ... from app.models import *
将数据发送到 Postgres
运行应用程序并通过表单提交一些数据(或在表中创建一些数据)。在 pgAdmin 中,右键单击您刚刚创建的表并刷新,然后右键单击并查看/编辑数据。
Could not send data to server: Socket is not connected (0x00002749/10057) could not send SSL negotiation packet: Socket is not connected (0x00002749/10057)
- 断开并重新连接服务器(右键单击服务器并单击断开服务器,然后单击连接服务器)并再次刷新表。
- 如果这不起作用,请右键单击服务器并单击属性,转到连接选项卡并将主机名/地址从 更改
localhost为127.0.0.1。然后重复步骤 1。
创建 Heroku 应用程序
由于我更喜欢在 Github 中直接使用 Heroku 而不是 CLI,因此我没有git init在此处使用,但请注意,如果您的代码还不是 Github 存储库,则需要使用它。
在命令行中:
heroku login # If you have the Heroku CLI installed correctly, this will open a tab in the browser and log you in to Heroku.
heroku create unique-app-name # (replace `unique-app-name` with your own name). This creates an app on the Heroku server, and it's the place your code is cloned to so that it can be run. Check that it has appeared in your [Heroku dashboard](https://dashboard.heroku.com/).
heroku addons:create heroku-postgresql:hobby-dev -a unique-app-name # This creates an empty postgres database for your app. Heroku uses its own database, not your pgAdmin database.
heroku config -a unique-app-name # The url you set earlier as the `SQLALCHEMY_DATABASE_URI` points to the database you created in pgAdmin, but since your app is now going to be using Heroku's database you need a new url. Copy the DATABASE_URL that is returned.
回到你app.config['SQLALCHEMY_DATABASE_URI']之前设置的代码,在else块中插入新的 url 。它应该看起来或多或少是这样的:
if ENV == 'dev':
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:123456@localhost/lexus'
else:
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://urlyoujustgotfromherokuozftkndvkayeyc:691196bfb1b1ca8318b733935b10c97a19fd41@ec2-52-71-161-140.compute-1.amazonaws.com:5432/d3pofh2b55a2ct'
如果您正在使用本教程的 github 存储库,请设置ENV = 'prod',否则将配置设置为使用您想要的 heroku url。
如果以下文件尚未包含在您的项目文件中,请将它们添加到您的根目录中:
# Procfile
web: gunicorn app:app # The first `app` refers to the app.py and the second `app` refers to the app object, ie `app = Flask(__name__)`. Heroku needs this to know how to run your code.
# runtime.txt
python-3.8.5 # Find your python version by entering `python --version` or `python3 --version` in the command line.
# requirements.txt
# Create this by running `pip3 freeze > requirements.txt`. According to the [Heroku docs](https://devcenter.heroku.com/articles/python-runtimes)
# this must be done after changing runtime versions, so it's best to do it last.
将所有内容推送到 Github(同样,这是如果您已经在仓库中,否则您将使用我没有遵循的 Heroku CLI 流程)。
在 Heroku 上部署
单击您之前在Heroku 仪表板中创建的应用程序,然后转到 Deploy 选项卡。在部署方法选项中,单击 Github。连接您的 Github 帐户和存储库。
向下滚动到手动部署部分,然后选择您要部署的分支(或者如果这是唯一的分支,则将其保留为 master)。单击部署分支。
Requested runtime (python-3.7.2) is not available for this stack (heroku-20). ! Aborting. More info: https://devcenter.heroku.com/articles/python-support ! Push rejected, failed to compile Python app. ! Push failed看起来python版本是错误的。检查
runtime.txt是否显示了正确的 python 版本。如果不是,更新它,删除并重新创建requirements.txt,推送到 Github 并再次单击 Deploy Branch。
创建 Heroku 数据库
回到命令行:
heroku run python3
>>> from app import db
>>> db.create_all()
要检查您的数据库,请输入
heroku pg:psql --app unique-app-name
如果你运行select * from tablename;什么都不会返回,因为还没有任何数据。
单击 Heroku 中的“查看”按钮以打开您的应用程序。提交表单(或输入数据,但您的应用程序如何工作),然后select * from tablename;再次运行,您将看到数据行。