ตั้งค่า 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
}
# ...

สิ่งที่เจอมากับตัวบ่อยๆ:

  1. "เอ๊ะ ทำไมมันยังเป็น SQLite อยู่เลย?"
    • เช็คดีๆ ว่า environ.Env.read_env() เรียกถูกที่ไหม path มันต้องชี้ไปที่ไฟล์ .env จริงๆ นะ
    • บางทีลืม pip install django-environ ก็มี
    • แล้วก็เช็คว่า DATABASE_URL ใน .env สะกดถูกไหม บางทีพิมพ์ localhost:5432 ผิดไปนิดเดียวก็เจ๊งละ
  2. 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. ลองเอาไปใช้กันดูนะ มันเวิร์คจริง!

Read more

PSG vs Monaco: ศึก 100 นัดเดือด ลีกเอิง และบทเรียนที่ปาร์ค เดส์ แพร็งซ์

PSG vs Monaco: ศึก 100 นัดเดือด ลีกเอิง และบทเรียนที่ปาร์ค เดส์ แพร็งซ์

สรุปผลและวิเคราะห์เกมเดือด PSG พบ Monaco ในลีกเอิงนัดที่ 25 ซึ่งเป็นการพบกันครั้งที่ 100 ในประวัติศาสตร์ลีก ความพ่ายแพ้ 1-3 คาบ้านของ PSG และบทบาทของ Akliouche พร้อมผลกระทบต่อเส้นทางแชมเปี้ยนส์ลีก

By ทีมงาน devdog
บาเยิร์นผงาดไร้เคน! ถล่มกลัดบัค 4-1 โชว์ความลึกของทีมก่อนลุยศึก UCL

บาเยิร์นผงาดไร้เคน! ถล่มกลัดบัค 4-1 โชว์ความลึกของทีมก่อนลุยศึก UCL

บาเยิร์น มิวนิค โชว์ฟอร์มแกร่ง แม้ไม่มีแฮร์รี่ เคน ถล่ม โบรุสเซีย มึนเชนกลัดบัค 4-1 ก่อนเตรียมลุยศึกแชมเปียนส์ลีกกับอตาลันต้า!

By ทีมงาน devdog
PSG: มหาอำนาจลูกหนังฝรั่งเศส กับศึกดวลเดือดโมนาโก และเป้าหมายสู่บัลลังก์ยุโรป

PSG: มหาอำนาจลูกหนังฝรั่งเศส กับศึกดวลเดือดโมนาโก และเป้าหมายสู่บัลลังก์ยุโรป

เจาะลึกเส้นทาง PSG สู่มหาอำนาจลูกหนัง วิเคราะห์สถานการณ์ลีกเอิง เตรียมพร้อมศึกใหญ่กับโมนาโก พร้อมความมุ่งมั่นสู่แชมป์ยุโรป

By ทีมงาน devdog
ลาลีกา: มนต์เสน่ห์ฟุตบอลสเปน, นวัตกรรมเรโทร, และบิ๊กแมตช์แห่งอนาคต

ลาลีกา: มนต์เสน่ห์ฟุตบอลสเปน, นวัตกรรมเรโทร, และบิ๊กแมตช์แห่งอนาคต

สำรวจลาลีกา ฟุตบอลสเปนอันทรงเสน่ห์ พร้อมไฮไลต์บิ๊กแมตช์ 2025/26 นวัตกรรมสัปดาห์เรโทร และบทบาทต่อวัฒนธรรมและเศรษฐกิจ.

By ทีมงาน devdog