Models.py ได้รับจำนวนมากวิธีที่ดีที่สุดในการทำลายคืออะไร


91

คำแนะนำจากหัวหน้างานของฉัน: "ฉันต้องการหลีกเลี่ยงการใส่ตรรกะใด ๆ ในส่วนmodels.pyนี้เรามาใช้เป็นเพียงคลาสสำหรับการเข้าถึงฐานข้อมูลและเก็บตรรกะทั้งหมดไว้ในคลาสภายนอกที่ใช้คลาสโมเดลหรือรวมเอาไว้"

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

มีวิธีง่ายๆในการใช้งาน ได้แก่ ? ใน PHP-speak ฉันต้องการเสนอต่อหัวหน้างานว่าเราเพิ่งmodels.pyรวม () คลาสโมเดลจากที่อื่น ๆ ตามแนวคิดแล้วสิ่งนี้จะช่วยให้โมเดลมีตรรกะทั้งหมดที่เราต้องการ แต่ลดขนาดไฟล์ลงโดยการเพิ่มจำนวนไฟล์ (ซึ่งนำไปสู่ปัญหาการควบคุมการแก้ไขน้อยลงเช่นความขัดแย้ง ฯลฯ )

ดังนั้นมีวิธีง่ายๆในการลบคลาสโมเดลออกจากไฟล์ models.py แต่โมเดลยังคงใช้งานได้กับเครื่องมือ Django ทั้งหมดหรือไม่? หรือมีวิธีแก้ไขปัญหาทั่วไปที่แตกต่างอย่างสิ้นเชิง แต่สวยงามสำหรับปัญหาทั่วไปของไฟล์ models.py "ขนาดใหญ่" หรือไม่? ข้อมูลใด ๆ จะได้รับการชื่นชม


7
คุณรู้คำสั่งนำเข้าใช่ไหม?
balpha

7
ปล. ฉันไม่ได้หมายความว่าน่ารังเกียจฉันแค่อยากรู้ว่าคุณอยู่ที่ไหน
balpha

1
ใช่ แต่ฉันไม่รู้ว่าเครื่องมือผู้ดูแลระบบของ django จะทำงานได้หรือไม่เพียงแค่ใช้คำสั่งนำเข้าเพื่อดึงโมเดลเข้ามา ฉันอยากจะถามที่นี่ดีกว่าใช้เวลามากมายในการลองใช้การนำเข้า ole ธรรมดาเพียงเพื่อค้นหาว่าเครื่องมือของ django ไม่สามารถเล่นได้ดีกับพวกเขา ฉันยอมรับว่าฉันใหม่กว่า python และ django ดังนั้นฉันอาจเข้าใจง่าย ๆ เกี่ยวกับคำสั่งนำเข้าเท่านั้น ...
แก้ไข

คำตอบ:


64

Django ออกแบบมาเพื่อให้คุณสร้างแอปพลิเคชันขนาดเล็กจำนวนมากแทนที่จะเป็นแอปพลิเคชันขนาดใหญ่

ภายในทุกแอปพลิเคชันขนาดใหญ่มีแอปพลิเคชันขนาดเล็กจำนวนมากที่ดิ้นรนเพื่อเป็นอิสระ

ถ้าคุณmodels.pyรู้สึกใหญ่แสดงว่าคุณทำมากเกินไป หยุด. ผ่อนคลาย. ย่อยสลาย.

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

พิจารณาเส้นทางการอัปเกรดของคุณและย่อยสลายแอปพลิเคชันที่คุณอาจต้องการแทนที่ในบางวัน คุณไม่จำเป็นต้องแทนที่มันจริงๆแต่คุณสามารถพิจารณาว่ามันเป็น "โมดูล" ของการเขียนโปรแกรมแบบสแตนด์อะโลนที่อาจถูกแทนที่ด้วยสิ่งที่เจ๋งกว่าในอนาคต

เรามีแอปพลิเคชันประมาณหนึ่งโหลแต่ละรายการmodel.pyมีรหัสไม่เกิน 400 บรรทัด พวกเขาทั้งหมดค่อนข้างมุ่งเน้นไปที่คำจำกัดความของคลาสที่ไม่ต่อเนื่องน้อยกว่าประมาณครึ่งโหล (สิ่งเหล่านี้ไม่ใช่ข้อ จำกัด ที่ยาก แต่เป็นการสังเกตเกี่ยวกับโค้ดของเรา)

เราย่อยสลายเร็วและบ่อยครั้ง


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

4
แม้ว่านี่จะเป็นวิธีที่ "ถูกต้อง" และเป็นประโยชน์ที่ควรทราบ แต่ก็ไม่ใช่สิ่งที่ฉันกำลังมองหา ฉันขออภัยหากไม่มีทางที่จะทราบว่าฉันกำลังมองหาคำตอบแบบใด :)
แก้ไข

@Eddified: ถ้าคุณไม่ทำสิ่งนี้มันมี แต่จะแย่ลง เริ่มแยกเลย
S.Lott

ตลกดีในขณะนี้ฉันกำลังฟัง Jacob Kaplan Moss (ที่ OSCON) อธิบายสิ่งนี้อย่างละเอียดและเป็นธรรมอย่างยิ่ง ;-)
Alex Martelli

13
คำตอบของ Glenn Maynard ดีกว่ามากสำหรับข้อนี้ การแบ่งเว็บแอปที่ซับซ้อนออกเป็นหลาย ๆ แอปนั้นเป็นแนวทางปฏิบัติที่ดี แต่การปรับโครงสร้างไฟล์ model.py ภายในแอปก็เช่นกัน การกระทำทั้งสองสามารถตั้งฉากกันได้
Erik

108

เป็นเรื่องปกติที่คลาสโมเดลจะมีวิธีการทำงานบนโมเดล ถ้าฉันมีแบบจำลองหนังสือด้วยวิธีการbook.get_noun_count()นั่นคือสิ่งที่เป็นของฉัน - ฉันไม่ต้องการที่จะต้องเขียน " get_noun_count(book)" เว้นแต่ว่าเมธอดนั้นจะอยู่ในแพ็คเกจอื่นจริงๆ (ตัวอย่างเช่นหากฉันมีแพ็คเกจสำหรับเข้าถึง API ของ Amazon ด้วย " get_amazon_product_id(book)")

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

site/models/__init__.py
site/models/book.py

__init__.py ดูเหมือน:

from .book import Book

ดังนั้นฉันจึงยังสามารถเขียน "from site.models import Book" ได้


สิ่งต่อไปนี้จำเป็นสำหรับเวอร์ชันก่อน Django 1.7 เท่านั้นโปรดดูที่ https://code.djangoproject.com/ticket/3591

เคล็ดลับเดียวคือคุณต้องตั้งค่าแอปพลิเคชันของแต่ละรุ่นอย่างชัดเจนเนื่องจากมีจุดบกพร่องใน Django: ถือว่าชื่อแอปพลิเคชันเป็นรายการที่สามถึงสุดท้ายในเส้นทางของโมเดล "site.models.Book" ให้ผลลัพธ์เป็น "site" ซึ่งถูกต้อง "site.models.book.Book" ทำให้คิดว่าชื่อแอปพลิเคชันคือ "โมเดล" นี่เป็นการแฮ็คที่น่ารังเกียจในส่วนของ Django ควรค้นหารายการแอปพลิเคชันที่ติดตั้งสำหรับคำนำหน้า

class Book(models.Model):
    class Meta: app_label = "site"

คุณอาจใช้คลาสพื้นฐานหรือเมตาคลาสเพื่อสรุปสิ่งนี้ได้ แต่ฉันยังไม่ได้ใส่ใจกับเรื่องนั้น


2
+1 ฉันใช้สิ่งนี้จนประสบความสำเร็จ ในขณะที่ S. Lott ถูกต้องในหลาย ๆ แอปซึ่งเป็นความคิดที่ดี แต่นี่เป็นวิธีแก้ปัญหาที่นี่และตอนนี้
Alexander Ljungberg

35
ฉันไม่เห็นประโยชน์มากนักในการแยกสิ่งต่างๆออกเป็นแอพต่างๆเมื่อโมเดลของคุณมีความสัมพันธ์กันอย่างใกล้ชิด
Glenn Maynard

2
สิ่งนี้ทำให้ฉันสนใจ ฉันอ่าน scompt ลิงก์ django wiki ที่โพสต์และพบว่า: "สิ่งนี้ได้รับการตรวจสอบแล้วว่าใช้งานได้โดยไม่มีป้ายกำกับคลาส Meta ในสาขาหลักปัจจุบัน" นั่นหมายความว่าหากคุณกำลังทำงานกับสาขาหลักเราสามารถทิ้งสิ่งของ Meta: app_label ได้หรือไม่ มันสับสนเพราะหลังจากความคิดเห็นเกี่ยวกับตั๋วเพื่อแก้ปัญหานี้
Dan.StackOverflow

2
ฉันเพิ่งทดสอบกับ trunk (ณ วันนี้ก่อนหน้านี้ r11286); หากไม่ได้ตั้งค่า app_name โมเดลก็จะไม่ปรากฏใน "sqlall appname" และอาจจะไม่ถูกสร้างขึ้นโดย syncdb (แต่ฉันไม่ได้ใช้มันจึงไม่สามารถทดสอบได้) เป็นกรณีข้อผิดพลาดที่ค่อนข้างสับสนเนื่องจากไม่ทำให้เกิดข้อผิดพลาดใด ๆ มันก็ไม่ปรากฏขึ้นอย่างเงียบ ๆ
Glenn Maynard

2
ว้าวเกือบ 10 ปีต่อมาและฉันยังคงรักโซลูชันนี้ เห็นด้วยว่าเป็นแนวทางที่ดีกว่าการแยกรหัสของคุณออกเป็นแอปขนาดเล็กซึ่งในความคิดของฉันอาจนำไปสู่ ​​codebase ที่ยากที่จะให้เหตุผล
Michael Hays

5

ฉันไม่สามารถเข้าใจได้ว่าคุณอาจมีปัญหาอะไรมากมาย คำตอบที่เป็นไปได้มีดังนี้

  • หลายรุ่นในไฟล์เดียวกัน

    ใส่ลงในไฟล์แยกกัน หากมีการอ้างอิงให้ใช้การนำเข้าเพื่อดึงโมเดลเพิ่มเติม

  • ฟังก์ชันตรรกะ / ยูทิลิตี้ภายนอกใน models.py

    ใส่ตรรกะพิเศษลงในไฟล์แยกกัน

  • วิธีการแบบคงที่สำหรับการเลือกอินสแตนซ์แบบจำลองบางส่วนจากฐานข้อมูล

    สร้างผู้จัดการใหม่ในไฟล์แยกต่างหาก

  • วิธีการที่เกี่ยวข้องกับแบบจำลองอย่างชัดเจน

    บันทึก __unicode__ และ get_absolute_url เป็นตัวอย่าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.