หลายต่อหลายคนในรายการแสดง django


94
class PurchaseOrder(models.Model):
    product = models.ManyToManyField('Product')
    vendor = models.ForeignKey('VendorProfile')
    dollar_amount = models.FloatField(verbose_name='Price')


class Product(models.Model):
   products = models.CharField(max_length=256)

   def __unicode__(self):
       return self.products

ฉันมีรหัสนั้น ขออภัยข้อผิดพลาดเกิดขึ้นใน admin.py พร้อมกับไฟล์ManyToManyField

class PurchaseOrderAdmin(admin.ModelAdmin):
    fields = ['product', 'dollar_amount']
    list_display = ('product', 'vendor')

ข้อผิดพลาดระบุว่า:

'PurchaseOrderAdmin.list_display [0]', 'product' คือ ManyToManyField ซึ่งไม่รองรับ

อย่างไรก็ตามมันจะรวบรวมเมื่อฉันนำ'product'ออกจากlist_display. ดังนั้นวิธีการที่ฉันสามารถแสดง'product'ในlist_displayโดยไม่ต้องให้มันข้อผิดพลาด?

แก้ไข : คำถามที่ดีกว่าอาจจะเป็นวิธีที่คุณแสดงManyToManyFieldในlist_display?

คำตอบ:


175

คุณอาจไม่สามารถทำได้โดยตรง จากเอกสารของlist_display

เขตข้อมูล ManyToManyField ไม่ได้รับการสนับสนุนเนื่องจากจะทำให้เกิดการเรียกใช้คำสั่ง SQL แยกกันสำหรับแต่ละแถวในตาราง หากคุณต้องการทำสิ่งนี้ให้กำหนดเมธอดแบบกำหนดเองของคุณและเพิ่มชื่อเมธอดนั้นใน list_display (ดูด้านล่างสำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการที่กำหนดเองใน list_display)

คุณสามารถทำสิ่งนี้:

class PurchaseOrderAdmin(admin.ModelAdmin):
    fields = ['product', 'dollar_amount']
    list_display = ('get_products', 'vendor')

    def get_products(self, obj):
        return "\n".join([p.products for p in obj.product.all()])

หรือกำหนดวิธีการแบบจำลองและใช้สิ่งนั้น

class PurchaseOrder(models.Model):
    product = models.ManyToManyField('Product')
    vendor = models.ForeignKey('VendorProfile')
    dollar_amount = models.FloatField(verbose_name='Price')

    def get_products(self):
        return "\n".join([p.products for p in self.product.all()])

และในส่วนของผู้ดูแลระบบ list_display

list_display = ('get_products', 'vendor')

นี่ดูเหมือนเป็นทางออกที่ดีจริงๆ ขอขอบคุณ. แม้ว่าตอนนี้ฉันได้รับข้อผิดพลาดว่า "ค่าว่างในคอลัมน์" product_id "ละเมิดข้อ จำกัด ที่ไม่เป็นค่าว่าง" มีความคิดอย่างไร
Mdjon26

3
เนื่องจากสิ่งนี้ทำให้ฐานข้อมูลลดลงคุณจะทำอย่างไรกับ select_related () หรือ prefetch_related () เพื่อปรับปรุงประสิทธิภาพ
Cloud Artisans

3
ในกรณีที่การเพิ่มประสิทธิภาพคำถามที่ยังคงน่าสนใจผมก็มีปัญหาเดียวกันและพบว่าคุณก็สามารถดำเนินการที่ดีที่สุดget_queryset()วิธีการของคุณModelAdminดูstackoverflow.com/questions/12354099/...
เก๊

1
@ SebastiánVansteenkisteความคิดที่ดีอาจcached_propertyจะช่วยได้ แต่ฉันคิดว่ามันคงจะไม่ เมื่อคุณใช้การปรับให้เหมาะสมget_querysetคุณสามารถยกตัวอย่างเช่นใส่คำอธิบายประกอบ / ประมวลผลข้อมูลล่วงหน้าได้ที่นั่นเช่นการเชื่อมต่อผลิตภัณฑ์ใน SQL แทนใน Django และจัดเก็บข้อมูลที่กำหนดเองของคุณในชุดแบบสอบถามของคุณ จากนั้นคุณจะต้องดำเนินการตรรกะนั้นเพียงครั้งเดียวใน SQL ไม่ใช่สำหรับทุกแถวเมื่อมีการเข้าถึงคุณสมบัติ
goetz

1
จุดดี. ฉันควรมองหาการเพิ่มประสิทธิภาพของตัวเองget_querysetฉันไม่ได้อ่านเอกสารฉบับเต็ม (และไม่พบตัวอย่างง่ายๆเพียงพอว่าฉันควรทำอะไร)
Sebastián Vansteenkiste

16

ด้วยวิธีนี้คุณสามารถทำได้โปรดตรวจสอบตัวอย่างต่อไปนี้:

class Categories(models.Model):
    """ Base category model class """

    title       = models.CharField(max_length=100)
    description = models.TextField()
    parent      = models.ManyToManyField('self', default=None, blank=True)
    when        = models.DateTimeField('date created', auto_now_add=True)

    def get_parents(self):
        return ",".join([str(p) for p in self.parent.all()])

    def __unicode__(self):
        return "{0}".format(self.title)

และในวิธีการเรียกโมดูล admin.py ของคุณดังนี้:

class categories(admin.ModelAdmin):
    list_display    = ('title', 'get_parents', 'when')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.