ตั้งค่า Django + PostgreSQL แบบไม่ปวดหัว (พร้อมจัดการ Secret)
คือบางทีเวลาเราเริ่มโปรเจค Django ใหม่ๆ เนี่ย มันก็มาพร้อม SQLite ใช่ป่ะ ซึ่งไอ้เจ้า SQLite เนี่ย มันก็ดีนะสำหรับdev เบาๆ หรือโปรเจคเล็กๆ แต่ถ้าจะเอาขึ้นโปรดักชั่นจริงๆ จังๆ หรือมีคนใช้เยอะๆ นี่สิ ต้อง PostgreSQL เท่านั้น! วันนี้เลยจะมาไกด์สั้นๆ ว่าจะเซ็ต Django ให้ไปคุยกับ PgSQL ยังไง พร้อมกับวิธีจัดการพวก Environment variable แบบเนียนๆ ด้วย django-environ จะได้ไม่ต้อง hardcode รหัสผ่านใน settings.py
เริ่มเลย!
อันดับแรกสุดนะ เข้าไปใน Virtual Env ก่อน ไม่งั้นเดี๋ยวเละ
python -m venv venv
source venv/bin/activate # บน Windows ใช้ `venv\Scripts\activate`
จากนั้นก็ติดตั้ง Django, psycopg2-binary, แล้วก็ django-environ
pip install Django psycopg2-binary django-environ
ทำไมต้อง psycopg2-binary? คือมัน install ง่ายดี ไม่ต้องไปงมหา lib ต่างๆ ในเครื่องให้วุ่นวายตอนแรกๆ อะนะ ถ้าใครอยาก compile เองก็ได้ไม่ว่ากัน แต่แนะนำอันนี้แหละสำหรับมือใหม่ (หรือคนขี้เกียจแบบผม ฮ่าๆ)
สร้างโปรเจค Django
ถ้ายังไม่มีก็สร้างไปเลย
django-admin startproject myproject .
python manage.py startapp myapp
แล้วก็อย่าลืมเพิ่ม 'myapp' เข้าไปใน INSTALLED_APPS ใน myproject/settings.py ด้วยนะ อันนี้เบสิก
ถึงเวลาเซ็ต PostgreSQL!
ตรงนี้แหละที่หลายคนชอบพลาด แรกสุดเลย ไปสร้าง DB ใน PostgreSQL ก่อน จะใช้ psql หรือ pgAdmin ก็ได้ ตามสะดวกเลย
CREATE DATABASE myproject_db;
CREATE USER myuser WITH PASSWORD 'mypassword';
ALTER ROLE myuser SET client_encoding TO 'utf8';
ALTER ROLE myuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE myuser SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE myproject_db TO myuser;
อันนี้คือแบบ quick-and-dirty นะ ถ้าเอาไปใช้จริงจังควรสร้าง role ให้ดีกว่านี้ มีสิทธิ์แค่ที่จำเป็นพอ
จัดการ Secret ด้วย django-environ
ตรงนี้สำคัญมาก! ใครที่เคยเผลอ commit รหัสผ่านขึ้น Git บ้างยกมือขึ้น! (ผมเองก็เคย 😅)
เราจะสร้างไฟล์ .env ไว้ที่ root ของโปรเจคเลย (ข้างๆ manage.py นั่นแหละ)
.env ไฟล์หน้าตาจะเป็นประมาณนี้:
SECRET_KEY=yoursecretkeyhere_long_random_string_
DEBUG=True
DATABASE_URL=postgres://myuser:mypassword@localhost:5432/myproject_db
ALLOWED_HOSTS=127.0.0.1,localhost
สำคัญ: อย่าลืมใส่ .env ไว้ใน .gitignore ด้วยนะ!
# .gitignore
.env
จากนั้น เปิด myproject/settings.py ขึ้นมา แล้วแก้ตรง DATABASES กับ SECRET_KEY
จากเดิมที่อาจจะเป็นแบบนี้:
# myproject/settings.py (เดิม)
# ...
SECRET_KEY = 'django-insecure-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
# ...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# ...
เปลี่ยนให้ใช้ django-environ ดึงค่าจาก .env แทน
# myproject/settings.py (ใหม่)
import os
import environ # เพิ่มบรรทัดนี้
env = environ.Env(
# set casting, default value
DEBUG=(bool, False) # บอกว่า DEBUG ถ้าไม่มีค่า จะให้เป็น False
)
# อ่านไฟล์ .env
environ.Env.read_env(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.env'))
# ...
SECRET_KEY = env('SECRET_KEY') # ดึงค่า SECRET_KEY จาก .env
# ...
DEBUG = env('DEBUG') # ดึงค่า DEBUG จาก .env
# ...
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS') # ดึงค่า ALLOWED_HOSTS จาก .env เป็น list
# ...
DATABASES = {
'default': env.db(), # ดึงค่า DATABASE_URL จาก .env
}
# ...
สิ่งที่เจอมากับตัวบ่อยๆ:
- "เอ๊ะ ทำไมมันยังเป็น SQLite อยู่เลย?"
- เช็คดีๆ ว่า
environ.Env.read_env()เรียกถูกที่ไหม path มันต้องชี้ไปที่ไฟล์.envจริงๆ นะ - บางทีลืม
pip install django-environก็มี - แล้วก็เช็คว่า
DATABASE_URLใน.envสะกดถูกไหม บางทีพิมพ์localhost:5432ผิดไปนิดเดียวก็เจ๊งละ
- เช็คดีๆ ว่า
psycopg2.OperationalError: fe_sendauth: no password supplied- อันนี้คือชัวร์เลยว่ารหัสผ่านที่ตั้งใน
.envไม่ตรงกับที่ตั้งใน PostgreSQL - หรือบางที User ที่ใช้ connect ไม่มีสิทธิ์พอ
- หรือไม่ก็ไม่ได้รัน PostgreSQL Server! (อันนี้ฮา แต่ก็เคยเจอคนลืม 🤣)
- อันนี้คือชัวร์เลยว่ารหัสผ่านที่ตั้งใน
ลอง python manage.py migrate ดู แล้วก็ python manage.py runserver ถ้าไม่มีอะไรผิดพลาด ก็ควรจะใช้ได้แล้ว
สรุปนะ: การใช้ django-environ มันทำให้ชีวิตเราง่ายขึ้นเยอะเลยนะเรื่องการจัดการ config พวก Database Credentials, API Keys อะไรพวกนี้อ่ะ มันดีกว่าการยัดทุกอย่างลง settings.py เยอะเลย ไม่ต้องกังวลเรื่องเผลอ commit ขึ้น Gitlab หรือ Github แถมยังปรับเปลี่ยน Environment ได้ง่ายด้วย เช่น Dev, Staging, Production. ลองเอาไปใช้กันดูนะ มันเวิร์คจริง!