ปรับปรุงการตั้งค่า Django ของคุณด้วย Type Hints: A Pydantic Tutorial

เผยแพร่แล้ว: 2022-07-22

โครงการ Django เคยทำให้ฉันหงุดหงิดเพราะฉันขาดวิธีการที่แข็งแกร่งและปรับขนาดได้เพื่อเพิ่มสภาพแวดล้อมใหม่ ด้วยการนำคำใบ้ประเภท pydantic และ Python มารวมกัน ฉันได้สร้างรากฐานอันทรงพลังที่ฉันต้องการ

ตามที่อธิบายไว้ใน PEP 484 คำแนะนำประเภทสนับสนุนการวิเคราะห์แบบสถิต แต่คำอธิบายประกอบเดียวกันนี้ยังพร้อมใช้งานในขณะใช้งานจริง แพ็คเกจของบริษัทอื่น เช่น การตรวจสอบประเภทรันไทม์ของข้อเสนอ pydantic ที่ใช้ข้อมูลเมตาเพิ่มเติมนี้ Pydantic ใช้คำแนะนำประเภท Python เพื่อช่วยจัดการข้อมูลเมตาของการตั้งค่าและดำเนินการตรวจสอบข้อมูลรันไทม์

กวดวิชา pydantic นี้จะแสดงผลเชิงบวกที่กว้างขวางของการใช้การจัดการการตั้งค่า pydantic กับ Django

การกำหนดค่าของเราเป็นไปตามแนวทางปฏิบัติที่ดีที่สุดที่อธิบายไว้ในเว็บไซต์แอพ Twelve-Factor:

  1. กำหนดคอนฟิกูเรชันที่ไม่คงที่และเป็นความลับเป็นตัวแปรสภาพแวดล้อม
  2. ในสภาพแวดล้อมการพัฒนา กำหนดตัวแปรสภาพแวดล้อมในไฟล์ .env และเพิ่ม . .env ไปที่ .gitignore
  3. ใช้กลไกของผู้ให้บริการระบบคลาวด์เพื่อกำหนด (ความลับ) ตัวแปรสภาพแวดล้อมสำหรับสภาพแวดล้อม QA การจัดเตรียม และการใช้งานจริง
  4. ใช้ไฟล์ settings.py ไฟล์เดียวที่กำหนดค่าตัวเองจากตัวแปรสภาพแวดล้อม
  5. ใช้ pydantic เพื่ออ่าน ตรวจสอบ ตรวจสอบ และตัวแปรสภาพแวดล้อม typecast บนตัวแปร Python ที่กำหนดการกำหนดค่า Django

นักพัฒนาซอฟต์แวร์บางรายสร้างไฟล์การตั้งค่าหลายไฟล์ เช่น settings_dev.py และ settings_prod.py น่าเสียดายที่แนวทางนี้ไม่สามารถปรับขนาดได้ดี ทำให้เกิดความซ้ำซ้อนของโค้ด ความสับสน ข้อบกพร่องที่หายาก และความพยายามในการบำรุงรักษาที่สูงขึ้น

การใช้แนวทางปฏิบัติที่ดีที่สุดที่กล่าวข้างต้น การเพิ่มสภาพแวดล้อมจำนวนเท่าใดก็ได้เป็นเรื่องง่าย มีการกำหนดไว้อย่างดี และป้องกันข้อผิดพลาดได้ แม้ว่าเราจะสำรวจการกำหนดค่าสภาพแวดล้อมที่ซับซ้อนกว่านี้ได้ แต่เราจะเน้นที่สองส่วนเพื่อความชัดเจน: การพัฒนาและการผลิต

สิ่งนี้มีลักษณะอย่างไรในทางปฏิบัติ?

การจัดการการตั้งค่า Pydantic และตัวแปรสภาพแวดล้อม

ตอนนี้เราเน้นที่ตัวอย่างทั้งในด้านการพัฒนาและการผลิต เราแสดงให้เห็นว่าแต่ละสภาพแวดล้อมกำหนดค่าการตั้งค่าต่างกันอย่างไร และ pydantic รองรับแต่ละสภาพแวดล้อมอย่างไร

แอปพลิเคชันตัวอย่างของเราต้องการฐานข้อมูลที่สนับสนุน Django ดังนั้นเราจึงจำเป็นต้องจัดเก็บสตริงการเชื่อมต่อฐานข้อมูล เราย้ายข้อมูลการกำหนดค่าการเชื่อมต่อฐานข้อมูลไปยังตัวแปรสภาพแวดล้อม DATABASE_URL โดยใช้แพ็คเกจ Python dj-database-url โปรดทราบว่าตัวแปรนี้เป็นประเภท str และจัดรูปแบบดังนี้:

 postgres://{user}:{password}@{hostname}:{port}/{database-name} mysql://{user}:{password}@{hostname}:{port}/{database-name} oracle://{user}:{password}@{hostname}:{port}/{database-name} sqlite:///PATH

ในสภาพแวดล้อมการพัฒนาของเรา เราสามารถใช้อินสแตนซ์ PostgreSQL ที่มี Docker เพื่อความสะดวกในการใช้งาน ในขณะที่ในสภาพแวดล้อมการใช้งานจริง เราจะชี้ไปที่บริการฐานข้อมูลที่จัดเตรียมไว้

ตัวแปรอื่นที่เราต้องการกำหนดคือบูลีน DEBUG ต้องไม่เปิดแฟล็ก DEBUG ใน Django ในการปรับใช้ที่ใช้งานจริง มีวัตถุประสงค์เพื่อรับข้อเสนอแนะเพิ่มเติมในระหว่างการพัฒนา ตัวอย่างเช่น ในโหมดดีบัก Django จะแสดงหน้าข้อผิดพลาดโดยละเอียดเมื่อมีข้อยกเว้นเกิดขึ้น

ค่านิยมการพัฒนาและการผลิตที่แตกต่างกันสามารถกำหนดได้ดังนี้

ชื่อตัวแปร การพัฒนา การผลิต
DATABASE_URL postgres://postgres:mypw@localhost:5432/mydb postgres://foo1:foo2@foo3:5432/foo4
DEBUG True False

เราใช้โมดูลการจัดการการตั้งค่า pydantic เพื่อจัดการชุดค่าตัวแปรสภาพแวดล้อมที่แตกต่างกันเหล่านี้ขึ้นอยู่กับสภาพแวดล้อม

ขั้นตอนการเตรียมการ

เพื่อนำไปปฏิบัติ เราเริ่มกำหนดค่าสภาพแวดล้อมการพัฒนาของเราโดยการสร้างไฟล์ .env ไฟล์เดียวที่มีเนื้อหานี้:

 DATABASE_URL=postgres://postgres:mypw@localhost:5432/mydb DEBUG=True

ต่อไป เราเพิ่มไฟล์ .env ลงในไฟล์ .gitignore ของโปรเจ็กต์ ไฟล์ .gitignore หลีกเลี่ยงการบันทึกข้อมูลที่อาจมีความละเอียดอ่อนในการควบคุมแหล่งที่มา

ในขณะที่วิธีนี้ใช้ได้ผลดีในสภาพแวดล้อมการพัฒนาของเรา ข้อมูลจำเพาะของสภาพแวดล้อมการผลิตของเราใช้กลไกที่แตกต่างออกไป แนวทางปฏิบัติที่ดีที่สุดของเรากำหนดว่าตัวแปรสภาพแวดล้อมการผลิตใช้ความลับของสภาพแวดล้อม ตัวอย่างเช่น ใน Heroku ความลับเหล่านี้เรียกว่า Config Vars และกำหนดค่าผ่าน Heroku Dashboard มีให้สำหรับแอปพลิเคชันที่ปรับใช้เป็นตัวแปรสภาพแวดล้อม:

สกรีนช็อตของเว็บอินเตอร์เฟส Config Vars แถบด้านข้างด้านซ้ายมีคำอธิบาย: "Config vars เปลี่ยนลักษณะการทำงานของแอป นอกเหนือจากการสร้างส่วนเสริมของคุณเองแล้ว ส่วนเสริมบางรายการยังมาพร้อมกับส่วนเสริมของตัวเอง" ส่วนหลักมีสองแถว แต่ละแถวจะมีช่องข้อความสองช่อง ไอคอนดินสอ และไอคอน X ฟิลด์ข้อความมีข้อมูลเดียวกันกับคอลัมน์ "ชื่อตัวแปร" และ "การผลิต" ในตารางก่อนหน้า มุมบนขวามีปุ่มที่ระบุว่า "ซ่อน Config Vars"

หลังจากนั้น เราจำเป็นต้องปรับการกำหนดค่าของแอปพลิเคชันเพื่ออ่านค่าเหล่านี้จากสภาพแวดล้อมใดสภาพแวดล้อมหนึ่งโดยอัตโนมัติ

การกำหนด settings.py . ของ Django

เริ่มต้นด้วยโครงการ Django ใหม่เพื่อให้มีโครงสร้างที่จำเป็นสำหรับตัวอย่างของเรา เรานั่งร้านโครงการ Django ใหม่ด้วยคำสั่งเทอร์มินัลต่อไปนี้:

 $ django-admin startproject mysite

ตอนนี้เรามีโครงสร้างพื้นฐานของโปรเจ็กต์สำหรับโปรเจ็กต์ mysite แล้ว โครงสร้างไฟล์ของโครงการมีดังนี้:

 mysite/ manage.py mysite/ __init__.py settings.py urls.py asgi.py wsgi.py

ไฟล์ settings.py มีโค้ดสำเร็จรูปที่ช่วยให้เราจัดการการกำหนดค่าแอปพลิเคชันได้ มีการตั้งค่าเริ่มต้นที่กำหนดไว้ล่วงหน้ามากมายที่เราต้องปรับให้เข้ากับสภาพแวดล้อมที่เกี่ยวข้อง

ในการจัดการการตั้งค่าแอปพลิเคชันเหล่านี้โดยใช้ตัวแปรสภาพแวดล้อมและ pydantic ให้เพิ่มโค้ดนี้ที่ด้านบนสุดของไฟล์ settings.py :

 import os from pathlib import Path from pydantic import ( BaseSettings, PostgresDsn, EmailStr, HttpUrl, ) import dj_database_url # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent class SettingsFromEnvironment(BaseSettings): """Defines environment variables with their types and optional defaults""" DATABASE_URL: PostgresDsn DEBUG: bool = False class Config: """Defines configuration for pydantic environment loading""" env_file = str(BASE_DIR / ".env") case_sensitive = True config = SettingsFromEnvironment() os.environ["DATABASE_URL"] = config.DATABASE_URL DATABASES = { "default": dj_database_url.config(conn_max_age=600, ssl_require=True) } DEBUG = config.DEBUG

รหัสนี้ทำสิ่งต่อไปนี้:

  • กำหนดคลาส SettingsFromEnvironment สืบทอดจากคลาส BaseSettings ของ BaseSettings
  • กำหนด DATABASE_URL และ DEBUG ตั้งค่าประเภทและตัวเลือกเริ่มต้นโดยใช้คำแนะนำประเภท Python
  • กำหนดคลาส Config ที่บอกให้ .env ค้นหาตัวแปรในไฟล์ .env หากไม่มีอยู่ในตัวแปรสภาพแวดล้อมของระบบ
  • สร้างอินสแตนซ์คลาส Config ลงในอ็อบเจ็กต์ config ; ตัวแปรที่ต้องการจะพร้อมใช้งานเป็น config.DATABASE_URL และ config.DEBUG
  • กำหนดตัวแปร Django ปกติ DATABASES และ DEBUG จากสมาชิกการกำหนด config เหล่านี้

รหัสเดียวกันทำงานในทุกสภาพแวดล้อม และ pydantic จะดูแลสิ่งต่อไปนี้:

  • ค้นหาตัวแปรสภาพแวดล้อม DATABASE_URL และ DEBUG
    • หากกำหนดเป็นตัวแปรสภาพแวดล้อม เช่น ในการผลิต จะใช้สิ่งเหล่านั้น
    • มิฉะนั้น จะดึงค่าเหล่านั้นจากไฟล์ . .env
    • หากไม่พบค่า จะทำสิ่งต่อไปนี้:
      • สำหรับ DATABASE_URL จะแสดงข้อผิดพลาด
      • สำหรับ DEBUG จะกำหนดค่าเริ่มต้น False
  • หากพบตัวแปรสภาพแวดล้อม ระบบจะตรวจสอบประเภทฟิลด์และให้ข้อผิดพลาดหากรายการใดรายการหนึ่งไม่ถูกต้อง:
    • สำหรับ DATABASE_URL จะตรวจสอบว่าประเภทฟิลด์เป็น URL แบบ PostgresDsn
    • สำหรับ DEBUG จะตรวจสอบว่าประเภทฟิลด์เป็น pydantic boolean ที่ถูกต้องและไม่เข้มงวด

โปรดสังเกตการตั้งค่าที่ชัดเจนของตัวแปรสภาพแวดล้อมของระบบปฏิบัติการจากค่าการกำหนดค่าสำหรับ DATABASE_URL อาจดูเหมือนซ้ำซ้อนในการตั้งค่า os.environ["DATABASE_URL"] = config.DATABASE_URL เนื่องจาก DATABASE_URL ถูกกำหนดให้เป็นตัวแปรสภาพแวดล้อมภายนอกแล้ว อย่างไรก็ตาม สิ่งนี้ทำให้ pydantic แยกวิเคราะห์ ตรวจสอบ และตรวจสอบความถูกต้องของตัวแปรนี้ได้ หากตัวแปรสภาพแวดล้อม DATABASE_URL หายไปหรือจัดรูปแบบไม่ถูกต้อง pydantic จะแสดงข้อความแสดงข้อผิดพลาดที่ชัดเจน การตรวจสอบข้อผิดพลาดเหล่านี้มีค่ามากเมื่อแอปพลิเคชันย้ายจากการพัฒนาไปสู่สภาพแวดล้อมที่ตามมา

หากไม่ได้กำหนดตัวแปร ค่าดีฟอลต์จะถูกกำหนดหรือข้อผิดพลาดจะแจ้งให้กำหนด พรอมต์ที่สร้างขึ้นจะระบุรายละเอียดประเภทตัวแปรที่ต้องการด้วย ประโยชน์ด้านข้างของการตรวจสอบเหล่านี้คือสมาชิกในทีมใหม่และวิศวกร DevOps ค้นพบได้ง่ายขึ้นว่าต้องกำหนดตัวแปรใดบ้าง วิธีนี้ช่วยหลีกเลี่ยงปัญหาที่ยากต่อการค้นหาซึ่งส่งผลให้เมื่อแอปพลิเคชันทำงานโดยไม่มีตัวแปรทั้งหมดที่กำหนดไว้

แค่นั้นแหละ. ขณะนี้แอปพลิเคชันมีการใช้งานการจัดการการตั้งค่าที่บำรุงรักษาได้โดยใช้ settings.py เวอร์ชันเดียว ความงามของแนวทางนี้คือช่วยให้เราสามารถระบุตัวแปรสภาพแวดล้อมที่ถูกต้องในไฟล์ .env หรือวิธีการอื่นๆ ที่ต้องการได้ผ่านสภาพแวดล้อมการโฮสต์ของเรา

เส้นทางที่ปรับขนาดได้

ฉันใช้การจัดการการตั้งค่า Django ด้วยการพิมพ์รันไทม์ pydantic ในโครงการ Django ทั้งหมดของฉัน ฉันพบว่ามันนำไปสู่ฐานโค้ดที่เล็กกว่าและบำรุงรักษาได้มากกว่า นอกจากนี้ยังมีวิธีการที่มีโครงสร้างที่ดี จัดทำเอกสารด้วยตนเอง และปรับขนาดได้เพื่อเพิ่มสภาพแวดล้อมใหม่

บทความถัดไปในชุดนี้เป็นบทช่วยสอนทีละขั้นตอนเกี่ยวกับการสร้างแอปพลิเคชัน Django ตั้งแต่เริ่มต้น พร้อมการจัดการการตั้งค่า pydantic และปรับใช้กับ Heroku


บล็อก Toptal Engineering ขอขอบคุณ Stephen Davidson สำหรับการตรวจสอบตัวอย่างโค้ดที่นำเสนอในบทความนี้

เวอร์ชันก่อนหน้าของบทความนี้เน้นย้ำถึงการเปิดตัว Python ที่เฉพาะเจาะจง เนื่องจาก Python รองรับคำแนะนำประเภทมาหลายปี เราจึงสรุปข้อความแนะนำโดยลบการอ้างอิงเวอร์ชันนี้