แยก views.py ในหลายไฟล์


153

ฉันviews.pyใหญ่เกินไปและยากที่จะหามุมมองที่ถูกต้อง

ฉันจะแบ่งไฟล์เป็นหลาย ๆ ไฟล์แล้วนำเข้าได้อย่างไร มันเกี่ยวข้องกับการลดความเร็วหรือไม่?

ฉันสามารถทำเช่นเดียวกันกับmodels.py?


4
ฉันแบ่งไฟล์ views.py ขนาดใหญ่ (7k บรรทัด) เป็นไฟล์แยกต่างหากและความเร็วก็เพิ่มขึ้นอย่างมาก
user1261774

คำตอบ:


190

ใน Django ทุกอย่างเป็นโมดูล Python (* .py) คุณสามารถสร้างโฟลเดอร์มุมมองพร้อมกับ__init__.pyด้านในและคุณจะยังสามารถนำเข้ามุมมองของคุณเพราะมันยังใช้โมดูล Python แต่ตัวอย่างจะดีกว่า

ต้นฉบับของคุณviews.pyอาจมีลักษณะเช่นนี้:

def view1(arg):
    pass

def view2(arg):
   pass

ด้วยโครงสร้างโฟลเดอร์ / ไฟล์ต่อไปนี้มันจะทำงานเหมือนกัน:

views/
   __init__.py
   viewsa.py
   viewsb.py

viewsa.py :

def view1(arg):
    pass

viewsb.py :

def view2(arg):
    pass

__init__.py :

from viewsa import view1
from viewsb import view2

รวดเร็วคำอธิบายจะเป็น: เมื่อคุณเขียนfrom views import view1หลามจะมองหาใน View1

  1. views.pyซึ่งเป็นสิ่งที่เกิดขึ้นในกรณีแรก (ดั้งเดิม)

  2. views/__init__.pyซึ่งเป็นสิ่งที่เกิดขึ้นในกรณีที่สอง ที่นี่__init__.pyสามารถให้วิธีการ view1 เพราะมันนำเข้า

ด้วยวิธีแก้ปัญหาแบบนี้คุณอาจไม่จำเป็นต้องเปลี่ยนimportหรือurlpatternโต้แย้งurls.py

หากคุณมีหลายวิธีในแต่ละไฟล์มุมมองใหม่คุณอาจพบว่ามีประโยชน์ในการนำเข้าที่views/__init__.pyใช้งาน*เช่นนี้:

from viewsa import *
from viewsb import *

ที่จริงฉันไม่รู้เกี่ยวกับปัญหาความเร็ว (แต่ฉันสงสัยว่ามี)

สำหรับรุ่นมันอาจจะยากสักหน่อย


2
คุณช่วยเพิ่มรูปแบบ URL ที่ตรงกับ view1 หรือ view2 ในตัวอย่างของคุณได้ไหม เพราะผมมีปัญหาเกี่ยวกับที่ ....
ปาสคาลไคลน์

2
ฉันพยายามทำสิ่งนี้ แต่เมื่อฉันนำเข้าโมเดลของฉัน (จาก app.models นำเข้า MyModel หรือจากโมเดลที่นำเข้า MyModel) Python บ่นว่าไม่มีโมเดล
Chris Miller

ไม่เป็นไรถ้าเราลบ views.py ในไดเรกทอรีรูท?
Roel

6
โซลูชันนี้ใช้งานไม่ได้สำหรับฉัน (ข้อผิดพลาดเดียวกันกับ @ChrisMiller การแก้ไขของฉัน: ใน__init__.py: from myapp.views.viewsa import *โปรดทราบว่าคุณไม่สามารถมี views.py ได้อีกต่อไป (หรืออย่างน้อยก็จะไม่สามารถอ่าน @ShiftNTab: ข้อผิดพลาดไม่ใช่ ค้นหามุมมองของคุณใน views.py) หวังว่ามันจะช่วยได้!
ThePhi

สิ่งที่เกี่ยวกับการตั้งชื่อ: ชื่อไฟล์ควรเป็นเอกพจน์หรือพหูพจน์? เช่น: views.car.pyvsviews.cars.py
guival

21

ฉันต้องทำสิ่งนี้มาก่อน (เพื่อความชัดเจน)

วิธีที่ฉันทำคือสร้างviewsไดเรกทอรีจากนั้นสร้างไฟล์ชื่อ__init__.py

ตอนนี้เมื่อคุณโทรหาurls.pyคุณเพียงแค่เพิ่มส่วนอื่น

ตัวอย่างเช่นก่อนหน้านี้คุณอาจเรียกว่า: -

url(r'^calendar/(?P<year>\d\d\d\d)/$', 'myproject.calendar.views.year')
url(r'^calendar/(?P<year>\d\d\d\d)/(?P<user>[a-z]+)/$', 'myproject.calendar.views.year_by_user')

ตอนนี้คุณสามารถโทรหาบางอย่างตามสายของ

url(r'^calendar/(?P<year>\d\d\d\d)/$', 'myproject.calendar.views.year.index')
url(r'^calendar/(?P<year>\d\d\d\d)/(?P<user>[a-z]+)/$', 'myproject.calendar.views.year.user')

แน่นอนนี่คือสมมติว่าคุณviews/year.pyมีหน้าที่indexและuser;)


10

โดยทั่วไปคุณสามารถใส่รหัสได้ทุกที่ที่คุณต้องการ urls.pyเพียงให้แน่ใจว่าคุณเปลี่ยนงบนำเข้าตามเช่นสำหรับมุมมองในการ

ไม่รู้รหัสจริงของคุณมันยากที่จะแนะนำสิ่งที่มีความหมาย บางทีคุณอาจจะใช้ประเภทของคำนำหน้าชื่อไฟล์เช่นบางviews_helper.py, views_fancy.py, views_that_are_not_so_often_used.pyหรือเพื่อ ...

อีกตัวเลือกหนึ่งที่จะสร้างviewsไดเรกทอรีกับ__init__.pyที่คุณนำเข้าทั้งหมดsubviews หากคุณต้องการไฟล์จำนวนมากคุณสามารถสร้างไฟล์ย่อยที่ซ้อนกันมากขึ้นเมื่อมุมมองของคุณเติบโต ...


8

เพียงเพื่อการแบ่งปันฉันมีปัญหาเล็กน้อยกับคำตอบของ Vincent Demeester ทุกอย่างเรียบร้อยยกเว้นในไฟล์init .py ฉันต้องเขียนด้วยวิธีนี้:

__init__.py :

from .viewsa import *
from .viewsb import *

วิธีนี้ฉันยังคงไม่จำเป็นต้องเปลี่ยนimportวิธีการของฉันใน urls.py ฉันอยู่ในPython 3.6.1และDjango 1.11.4


5

คำตอบง่ายๆ: ใช่

ดีที่สุดคือการสร้างไดเรกทอรีที่เรียกว่า views จากนั้นใน urls.py ของคุณ:

import views
...
url(r'^classroom$', views.school.klass, name="classroom"),

1

ฉันแบ่งมุมมองเกือบทั้งหมดในแอพของฉันให้เป็นโฟลเดอร์มุมมอง ( แน่นอนว่าเป็นinit .py) อย่างไรก็ตามฉันไม่ได้นำเข้าการชมย่อยทั้งหมดในinit .py เช่นเดียวกับคำตอบที่แนะนำ ดูเหมือนว่าจะทำงานได้ดี


1

เนื่องจาก Django คาดหวังว่ามุมมองจะเป็นวัตถุที่เรียกได้คุณจึงสามารถใส่ได้ทุกที่ใน PYTHONPATH ของคุณ ดังนั้นคุณสามารถทำได้เช่นสร้างแพ็คเกจ myapp.views ใหม่และใส่มุมมองลงในหลาย ๆ โมดูล โดยปกติคุณจะต้องอัปเดต urls.py และโมดูลอื่น ๆ ที่อ้างอิง callables มุมมองเหล่านี้


1
สิ่งนี้ไม่ถูกต้องจริง - สามารถทำได้กับรุ่น ดู: code.djangoproject.com/ticket/4470
Jonathan Berger

1
อารู้ดีขอบคุณ :-) ฉันคิดเสมอว่ามีเวทมนตร์เพิ่มขึ้นอีกเล็กน้อยที่เกี่ยวข้องกับโมเดลและวิธีที่พวกเขาอาศัยอยู่ในแพ็คเกจแอป ลบบรรทัดเกี่ยวกับแบบจำลองในการตอบกลับของฉัน
Horst Gutmann

ดีใจที่ฉันสามารถช่วยฉันรู้ในภายหลังว่าลิงค์นี้จริงอธิบายว่ามันทำกับแบบจำลองที่ดีขึ้นมาก: blog.amber.org/2009/01/19/…
Jonathan Berger

1

ฉันได้เล่นโดยใส่สิ่งนี้ลงในinit .py ของฉัน:

import os

currPath = os.path.realpath(os.path.dirname(__file__))

dirFiles = []
for root, dirs, files in os.walk(currPath):
    for name in files:
        if name.endswith('.py') and not name.startswith('_'): 
            dirFiles.append(name.strip('.py'))

for f in dirFiles:
    exec("from %s import %s" % (f,f))

ฉันยังใหม่กับงูใหญ่ดังนั้นฉันยังคงดูว่ามันมีผลต่อความเร็ว / ความปลอดภัย / ความง่ายในการใช้งานอย่างไร


1

สมมติว่าคุณมีไฟล์ชื่อ: password_generator.pyแล้วviews.pyเพิ่มภายใน:from password_generator import *

จากนั้นคุณสามารถเรียกใช้ฟังก์ชันของโมดูลviews.pyนั้นได้


1

คำตอบของVincent Demeesterนั้นยอดเยี่ยมมาก! แต่สำหรับฉันคำตอบที่ติดได้ทำงานเหมือนจับใจ ฉันประสบปัญหาในการย้ายฐานข้อมูล ข้อผิดพลาดระบุบรรทัดที่นำเข้าโมเดลแรกและแจ้งว่าไม่รู้จักโมดูลแอปของฉัน ค้นหามาก แต่ไม่พบวิธีแก้ปัญหา แต่ต่อมาฉันนำเข้าโมเดลเช่นนี้:

from ..models import ModelName

มันได้ผล !!

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