Django - จำกัด ผลลัพธ์การสืบค้น


200

ฉันต้องการใช้อินสแตนซ์ 10 รุ่นสุดท้ายและมีรหัสนี้:

 Model.objects.all().order_by('-id')[:10]

เป็นความจริงหรือไม่ที่รับอินสแตนซ์ทั้งหมดก่อนจากนั้นจึงใช้เพียง 10 ครั้งล่าสุดเท่านั้น มีวิธีใดที่มีประสิทธิภาพมากกว่านี้ไหม?


คำตอบ:


304

ชุดค้นหา Django ขี้เกียจ นั่นหมายความว่าแบบสอบถามจะเข้าสู่ฐานข้อมูลเฉพาะเมื่อคุณขอผลลัพธ์โดยเฉพาะ

ดังนั้นจนกว่าคุณจะพิมพ์หรือใช้ผลลัพธ์ของแบบสอบถามคุณสามารถกรองเพิ่มเติมโดยไม่มีการเข้าถึงฐานข้อมูล

ดังที่คุณเห็นด้านล่างรหัสของคุณเรียกใช้คิวรีหนึ่ง sql เพื่อดึงข้อมูลเฉพาะ 10 รายการสุดท้าย

In [19]: import logging                                 
In [20]: l = logging.getLogger('django.db.backends')    
In [21]: l.setLevel(logging.DEBUG)                      
In [22]: l.addHandler(logging.StreamHandler())      
In [23]: User.objects.all().order_by('-id')[:10]          
(0.000) SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" ORDER BY "auth_user"."id" DESC LIMIT 10; args=()
Out[23]: [<User: hamdi>]

ฉันลองมันใน mongoDB และมันบอกว่า SELECT ไม่ได้รับการสนับสนุน วิธีการทำเช่นนี้ใน mongoDB?
winux

@winux เนื่องจากนี่เป็นเฉพาะของ Django ดูเหมือนว่าคุณอาจจำเป็นต้องตั้งค่า Django ให้ทำงานกับฐานข้อมูลประเภท Mongo / NoSQL โดยเฉพาะ นั่นไม่ใช่การตั้งค่าทั่วไปในประสบการณ์ของฉันเกี่ยวกับการตั้งค่ามาตรฐาน Django ORM
คนขี้ขลาดนิรนาม

38

ที่จริงฉันคิดว่าLIMIT 10จะถูกส่งไปยังฐานข้อมูลดังนั้นการแบ่งส่วนจะไม่เกิดขึ้นใน Python แต่ในฐานข้อมูล

ดูการ จำกัด ชุดแบบสอบถามสำหรับข้อมูลเพิ่มเติม


โปรดทราบว่าวิธีนี้ใช้ไม่ได้กับชุดการสืบค้นที่ต้องมีการกรองเนื่องจากคุณไม่สามารถกรองได้หลังจากการแบ่งส่วน
Kamermans ของไมค์ 'Pomax'

2
ดังนั้นกรองก่อนที่จะฝานมัน ขอบคุณ Davor สำหรับลิงค์!
Vyachez

13

ดูเหมือนว่าโซลูชันในคำถามจะไม่ทำงานกับ Django 1.7 อีกต่อไปและทำให้เกิดข้อผิดพลาด: "ไม่สามารถเรียงลำดับข้อความค้นหาใหม่ได้เมื่อมีการใช้งานชิ้น"

ตามเอกสารhttps://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysetsบังคับให้พารามิเตอร์“ ขั้นตอน” ของ Pice Slice ของไวยากรณ์ประเมินแบบสอบถาม มันทำงานด้วยวิธีนี้:

Model.objects.all().order_by('-id')[:10:1]

ยังคงฉันสงสัยว่าขีด จำกัด จะดำเนินการใน SQL หรือ Python ชิ้นผลอาร์เรย์ทั้งหมดส่งกลับ ไม่มีประโยชน์ที่จะเรียกรายการขนาดใหญ่ไปยังหน่วยความจำแอปพลิเคชัน


แม้แต่วิธีนี้ก็ใช้ไม่ได้กับ django> = 1.8 ที่ทดสอบแล้ว
sonus21

3

ใช่. หากคุณต้องการดึงข้อมูลชุดย่อยของวัตถุที่ จำกัด คุณสามารถใช้รหัสด้านล่าง:

ตัวอย่าง:

obj=emp.objects.all()[0:10]

จุดเริ่มต้น 0 เป็นทางเลือกดังนั้น

obj=emp.objects.all()[:10]

โค้ดด้านบนส่งคืน 10 อินสแตนซ์แรก


1

ในฐานะที่เป็นส่วนเสริมและการสังเกตคำตอบที่มีประโยชน์อื่น ๆ มันก็คุ้มค่าที่จะสังเกตว่าการ [:10]แบ่งส่วนข้อมูลจะส่งคืน10 องค์ประกอบแรกของรายการไม่ใช่ 10 รายการสุดท้าย

ในการรับ 10 คนสุดท้ายคุณควรทำ[-10:]แทน (ดูที่นี่ ) สิ่งนี้จะช่วยคุณหลีกเลี่ยงการใช้order_by('-id')กับ-เพื่อย้อนกลับองค์ประกอบ


1
ฉันลองและได้รับ "การจัดทำดัชนีเชิงลบไม่ได้รับการสนับสนุน"
bparker

@DarkCygnus Product.objects.filter(~Q(price=0))[-5:]ทำให้ฉันเกิดข้อผิดพลาดเดียวกัน: "ไม่รองรับการสร้างดัชนีเชิงลบ"
bersam

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