Di bagian ini kita akan menyiapkan database Postgres untuk menyimpan hasil jumlah kata kita serta SQLAlchemy, Object Relational Mapper, dan Alembic untuk menangani migrasi database.
Bonus Gratis: Klik di sini untuk mendapatkan akses ke video tutorial Flask + Python gratis yang menunjukkan cara membuat aplikasi web Flask, langkah demi langkah.
Pembaruan:
- 09/02/2020:Upgrade ke Python versi 3.8.1 serta versi terbaru dari Psycopg2, Flask-SQLAlchemy, dan Flask-Migrate. Lihat di bawah untuk detailnya. Instal dan gunakan Flask-Script secara eksplisit karena perubahan antarmuka internal Flask-Migrate.
- 22/03/2016:Ditingkatkan ke Python versi 3.5.1 serta versi terbaru dari Psycopg2, Flask-SQLAlchemy, dan Flask-Migrate. Lihat di bawah untuk detailnya.
- 22/02/2015:Menambahkan dukungan Python 3.
Ingat:Inilah yang sedang kami bangun - Aplikasi Flask yang menghitung pasangan frekuensi kata berdasarkan teks dari URL yang diberikan.
- Bagian Satu:Siapkan lingkungan pengembangan lokal, lalu terapkan lingkungan staging dan produksi di Heroku.
- Bagian Kedua:Menyiapkan database PostgreSQL bersama dengan SQLAlchemy dan Alembic untuk menangani migrasi. (saat ini )
- Bagian Tiga:Tambahkan logika back-end untuk mengikis lalu proses jumlah kata dari halaman web menggunakan perpustakaan permintaan, BeautifulSoup, dan Natural Language Toolkit (NLTK).
- Bagian Empat:Menerapkan antrian tugas Redis untuk menangani pemrosesan teks.
- Bagian Lima:Siapkan Angular di front-end untuk terus melakukan polling di back-end untuk melihat apakah permintaan sudah selesai diproses.
- Bagian Enam:Mendorong ke server staging di Heroku - menyiapkan Redis dan merinci cara menjalankan dua proses (web dan pekerja) pada satu Dyno.
- Bagian Tujuh:Perbarui front-end agar lebih ramah pengguna.
- Bagian Delapan:Buat Arahan Sudut khusus untuk menampilkan bagan distribusi frekuensi menggunakan JavaScript dan D3.
Butuh kode? Ambil dari repo.
Persyaratan Pemasangan
Alat yang digunakan di bagian ini:
- PostgreSQL (11.6)
- Psycopg2 (2.8.4) - adaptor Python untuk Postgres
- Flask-SQLAlchemy (2.4.1) - Ekstensi Flask yang menyediakan dukungan SQLAlchemy
- Flask-Migrate (2.5.2) - ekstensi yang mendukung migrasi database SQLAlchemy melalui Alembic
Untuk memulai, instal Postgres di komputer lokal Anda, jika Anda belum memilikinya. Karena Heroku menggunakan Postgres, ada baiknya kita mengembangkan secara lokal di database yang sama. Jika Anda belum menginstal Postgres, Postgres.app adalah cara mudah untuk memulai dan menjalankan untuk pengguna Mac OS X. Lihat halaman unduh untuk info lebih lanjut.
Setelah Anda menginstal dan menjalankan Postgres, buat database bernama wordcount_dev
untuk digunakan sebagai basis data pengembangan lokal kami:
$ psql
# create database wordcount_dev;
CREATE DATABASE
# \q
Untuk menggunakan database kami yang baru dibuat dalam aplikasi Flask, kami perlu menginstal beberapa hal:
$ cd flask-by-example
cd
masuk ke direktori harus mengaktifkan lingkungan virtual dan mengatur variabel lingkungan yang ditemukan di.env
file melalui autoenv, yang kami siapkan di bagian 1.
$ python -m pip install psycopg2==2.8.4 Flask-SQLAlchemy===2.4.1 Flask-Migrate==2.5.2
$ python -m pip freeze > requirements.txt
Jika Anda menggunakan OS X dan mengalami masalah saat menginstal psycopg2, lihat artikel Stack Overflow ini.
Anda mungkin perlu menginstal
psycopg2-binary
bukannyapsycopg2
jika instalasi Anda gagal.
Perbarui Konfigurasi
Tambahkan SQLALCHEMY_DATABASE_URI
bidang ke Config()
kelas di config.py . Anda file untuk menyetel aplikasi Anda agar menggunakan database yang baru dibuat dalam pengembangan (lokal), staging, dan produksi:
import os
class Config(object):
...
SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']
config.py . Anda file sekarang akan terlihat seperti ini:
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
DEBUG = False
TESTING = False
CSRF_ENABLED = True
SECRET_KEY = 'this-really-needs-to-be-changed'
SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']
class ProductionConfig(Config):
DEBUG = False
class StagingConfig(Config):
DEVELOPMENT = True
DEBUG = True
class DevelopmentConfig(Config):
DEVELOPMENT = True
DEBUG = True
class TestingConfig(Config):
TESTING = True
Sekarang ketika konfigurasi kita dimuat ke dalam aplikasi kita, database yang sesuai juga akan terhubung dengannya.
Mirip dengan bagaimana kami menambahkan variabel lingkungan di posting terakhir, kami akan menambahkan DATABASE_URL
variabel. Jalankan ini di terminal:
$ export DATABASE_URL="postgresql:///wordcount_dev"
Dan kemudian tambahkan baris itu ke .env . Anda berkas.
Di app.py . Anda file impor SQLAlchemy dan sambungkan ke database:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
from models import Result
@app.route('/')
def hello():
return "Hello World!"
@app.route('/<name>')
def hello_name(name):
return "Hello {}!".format(name)
if __name__ == '__main__':
app.run()
Model Data
Siapkan model dasar dengan menambahkan models.py berkas:
from app import db
from sqlalchemy.dialects.postgresql import JSON
class Result(db.Model):
__tablename__ = 'results'
id = db.Column(db.Integer, primary_key=True)
url = db.Column(db.String())
result_all = db.Column(JSON)
result_no_stop_words = db.Column(JSON)
def __init__(self, url, result_all, result_no_stop_words):
self.url = url
self.result_all = result_all
self.result_no_stop_words = result_no_stop_words
def __repr__(self):
return '<id {}>'.format(self.id)
Di sini kami membuat tabel untuk menyimpan hasil penghitungan kata.
Pertama-tama kita mengimpor koneksi database yang kita buat di app.py file serta JSON dari dialek PostgreSQL SQLAlchemy. Kolom JSON cukup baru untuk Postgres dan tidak tersedia di setiap database yang didukung oleh SQLAlchemy sehingga kami perlu mengimpornya secara khusus.
Selanjutnya kita membuat Result()
class dan memberinya nama tabel results
. Kami kemudian mengatur atribut yang ingin kami simpan untuk hasil-
id
dari hasil yang kami simpanurl
bahwa kami menghitung kata-kata dari- daftar lengkap kata yang kami hitung
- daftar kata yang kami hitung dikurangi kata berhenti (lebih lanjut tentang ini nanti)
Kami kemudian membuat __init__()
metode yang akan dijalankan saat pertama kali kita membuat hasil baru dan, akhirnya, sebuah __repr__()
metode untuk mewakili objek saat kita memintanya.
Migrasi Lokal
Kami akan menggunakan Alembic, yang merupakan bagian dari Flask-Migrate, untuk mengelola migrasi database untuk memperbarui skema database.
Catatan: Flask-Migrate menggunakan alat CLI Flask yang baru. Namun, artikel ini menggunakan antarmuka yang disediakan oleh Flask-Script, yang digunakan sebelumnya oleh Flask-Migrate. Untuk menggunakannya, Anda perlu menginstalnya melalui:
$ python -m pip install Flask-Script==2.0.6 $ python -m pip freeze > requirements.txt
Buat file baru bernama manage.py :
import os
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from app import app, db
app.config.from_object(os.environ['APP_SETTINGS'])
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
Untuk menggunakan Flask-Migrate kami mengimpor Manager
serta Migrate
dan MigrateCommand
ke manage.py . kami mengajukan. Kami juga mengimpor app
dan db
jadi kami memiliki akses ke mereka dari dalam skrip.
Pertama, kami mengatur konfigurasi kami untuk mendapatkan lingkungan kami - berdasarkan variabel lingkungan - membuat instance migrasi, dengan app
dan db
sebagai argumen, dan siapkan manager
perintah untuk menginisialisasi Manager
contoh untuk aplikasi kita. Terakhir, kami menambahkan db
perintah ke manager
sehingga kita dapat menjalankan migrasi dari baris perintah.
Untuk menjalankan migrasi, inisialisasi Alembic:
$ python manage.py db init
Creating directory /flask-by-example/migrations ... done
Creating directory /flask-by-example/migrations/versions ... done
Generating /flask-by-example/migrations/alembic.ini ... done
Generating /flask-by-example/migrations/env.py ... done
Generating /flask-by-example/migrations/README ... done
Generating /flask-by-example/migrations/script.py.mako ... done
Please edit configuration/connection/logging settings in
'/flask-by-example/migrations/alembic.ini' before proceeding.
Setelah Anda menjalankan inisialisasi database, Anda akan melihat folder baru bernama "migrasi" di proyek. Ini memegang pengaturan yang diperlukan untuk Alembic untuk menjalankan migrasi terhadap proyek. Di dalam "migrasi" Anda akan melihat folder bernama "versi", yang akan berisi skrip migrasi saat dibuat.
Mari kita buat migrasi pertama kita dengan menjalankan migrate
perintah.
$ python manage.py db migrate
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.autogenerate.compare] Detected added table 'results'
Generating /flask-by-example/migrations/versions/63dba2060f71_.py
... done
Sekarang Anda akan melihat di folder "versi" Anda ada file migrasi. File ini dibuat secara otomatis oleh Alembic berdasarkan modelnya. Anda dapat membuat (atau mengedit) file ini sendiri; namun, untuk sebagian besar kasus, file yang dibuat secara otomatis akan melakukannya.
Sekarang kita akan menerapkan upgrade ke database menggunakan db upgrade
perintah:
$ python manage.py db upgrade
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 63dba2060f71, empty message
Basis data sekarang siap untuk kita gunakan di aplikasi kita:
$ psql
# \c wordcount_dev
You are now connected to database "wordcount_dev" as user "michaelherman".
# \dt
List of relations
Schema | Name | Type | Owner
--------+-----------------+-------+---------------
public | alembic_version | table | michaelherman
public | results | table | michaelherman
(2 rows)
# \d results
Table "public.results"
Column | Type | Modifiers
----------------------+-------------------+------------------------------------------------------
id | integer | not null default nextval('results_id_seq'::regclass)
url | character varying |
result_all | json |
result_no_stop_words | json |
Indexes:
"results_pkey" PRIMARY KEY, btree (id)
Migrasi Jarak Jauh
Terakhir, mari kita terapkan migrasi ke database di Heroku. Namun, pertama-tama, kita perlu menambahkan detail basis data staging dan produksi ke config.py berkas.
Untuk memeriksa apakah kita memiliki database yang disiapkan di server staging, jalankan:
$ heroku config --app wordcount-stage
=== wordcount-stage Config Vars
APP_SETTINGS: config.StagingConfig
Pastikan untuk mengganti
wordcount-stage
dengan nama aplikasi pementasan Anda.
Karena kita tidak melihat variabel lingkungan database, kita perlu menambahkan addon Postgres ke server staging. Untuk melakukannya, jalankan perintah berikut:
$ heroku addons:create heroku-postgresql:hobby-dev --app wordcount-stage
Creating postgresql-cubic-86416... done, (free)
Adding postgresql-cubic-86416 to wordcount-stage... done
Setting DATABASE_URL and restarting wordcount-stage... done, v8
Database has been created and is available
! This database is empty. If upgrading, you can transfer
! data from another database with pg:copy
Use `heroku addons:docs heroku-postgresql` to view documentation.
hobby-dev
adalah tingkat gratis dari addon Heroku Postgres.
Sekarang ketika kita menjalankan heroku config --app wordcount-stage
sekali lagi kita akan melihat pengaturan koneksi untuk database:
=== wordcount-stage Config Vars
APP_SETTINGS: config.StagingConfig
DATABASE_URL: postgres://azrqiefezenfrg:Zti5fjSyeyFgoc-U-yXnPrXHQv@ec2-54-225-151-64.compute-1.amazonaws.com:5432/d2kio2ubc804p7
Selanjutnya kita perlu mengkomit perubahan yang telah Anda buat ke git dan push ke server staging Anda:
$ git push stage master
Jalankan migrasi yang kita buat untuk memigrasi database staging dengan menggunakan heroku run
perintah:
$ heroku run python manage.py db upgrade --app wordcount-stage
Running python manage.py db upgrade on wordcount-stage... up, run.5677
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 63dba2060f71, empty message
Perhatikan bagaimana kami hanya menjalankan
upgrade
, bukaninit
ataumigrate
perintah seperti sebelumnya. Kami sudah menyiapkan file migrasi dan siap digunakan; kita hanya perlu menerapkannya pada database Heroku.
Sekarang mari kita lakukan hal yang sama untuk produksi.
- Siapkan database untuk aplikasi produksi Anda di Heroku, seperti yang Anda lakukan untuk pementasan:
heroku addons:create heroku-postgresql:hobby-dev --app wordcount-pro
- Dorong perubahan Anda ke situs produksi Anda:
git push pro master
Perhatikan bagaimana Anda tidak perlu membuat perubahan apa pun pada file konfigurasi - ini mengatur database berdasarkanDATABASE_URL
yang baru dibuat variabel lingkungan. - Terapkan migrasi:
heroku run python manage.py db upgrade --app wordcount-pro
Sekarang baik lokasi pementasan maupun produksi kami telah menyiapkan basis datanya dan dimigrasikan - dan siap digunakan!
Saat Anda menerapkan migrasi baru ke database produksi, mungkin ada waktu henti. Jika ini merupakan masalah, Anda dapat mengatur replikasi basis data dengan menambahkan basis data “pengikut” (umumnya dikenal sebagai budak). Untuk informasi lebih lanjut tentang ini, lihat dokumentasi resmi Heroku.
Kesimpulan
Itu saja untuk bagian 2. Jika Anda ingin menggali lebih dalam tentang Flask, lihat seri video kami yang menyertainya:
Bonus Gratis: Klik di sini untuk mendapatkan akses ke video tutorial Flask + Python gratis yang menunjukkan cara membuat aplikasi web Flask, langkah demi langkah.
Di Bagian 3 kita akan membangun fungsionalitas penghitungan kata dan mengirimkannya ke antrean tugas untuk menangani pemrosesan penghitungan kata yang berjalan lebih lama.
Sampai jumpa lain waktu. Semangat!
Ini adalah karya kolaborasi antara Cam Linke, salah satu pendiri Startup Edmonton, dan orang-orang di Real Python.