ตัวจัดการแบบกำหนดเองตัวเดียวสำหรับหลายรุ่นใน Django

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

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

ฉันรู้ว่าผู้จัดการสามารถเข้าถึง self.model เพื่อรับโมเดลที่แนบมาด้วย

Class Main(models.Model)
  owner=models.ForeignKey (User)
  owned = OwnedManager()

Class Second(models.Model)
  main=models.ForeignKey('Main')
  owned = OwnedManager()

Class Third(models.Model)
  second=models.ForeignKey('Second')
  owned = OwnedManager()

ฉันต้องการให้ Custom Manager ของฉันมีพฤติกรรมประเภทนี้:

class OwnedManager(models.Manager): 
    def get_owned_objs(self, owner):
        if self.model == 'Main': # WRONG: How do I get the model name?
            owned_main = self.filter(owner=owner)
            return owned_main
        elif self.model == 'Second':
            owned_second = self.filter(main__owner=owner)
            return owned_second
        else:
            owned_third = self.filter(second__main__owner=owner)
            return owned_third

เพื่อให้มีวิธีเรียกข้ามรุ่นต่างๆ ที่สอดคล้องกัน เช่น:

main_object.owned.get_owned_objs(owner=user1) # of the Model Main
second_object.owned.get_owned_objs(owner=user1) # of the Model Second
third_object.owned.get_owned_objs(owner=user1) # of the Model Third

คำถาม:

  • self.model == 'Main' ผิด ฉันไม่ได้ชื่อรุ่นเช่นนี้ มีวิธีที่จะได้รับมันหรือไม่?
  • สิ่งนี้มีประสิทธิภาพหรือไม่? คุณรู้วิธีที่ดีกว่าในการดำเนินการนี้หรือไม่? บางทีอาจเป็นมรดกผู้จัดการแบบกำหนดเอง?

แก้ไข - วิธีแก้ปัญหาของฉัน: คำตอบที่ยอมรับด้านล่างเป็นวิธีแก้ปัญหาที่ดี แต่ฉันยังพบวิธีรับชื่อรุ่นของรุ่นนั้น ๆ ที่เรียกใช้ตัวจัดการแบบกำหนดเองด้วย นั่นคือ:

if self.model.__name__ == 'Main':

กุญแจสำคัญที่นี่คือแอตทริบิวต์ __name__


person Leonardo    schedule 31.07.2013    source แหล่งที่มา


คำตอบ (1)


1) สร้างแบบจำลองนามธรรม

class AbstractModel(models.Model):
    class Meta(models.Meta):
        abstract = True

    objects = OwnedManager()

2) สืบทอดโมเดลของคุณจาก AbstractModel ใส่คีย์บางส่วนใน meta

class Model(AbstractModel)
    class Meta(AbstractModel.Meta):
        filter_key = 'some_key'

3) ออกแบบ OwnedManager ของคุณใหม่

class OwnedManager(models.Manager): 
    def get_owned_objs(self, owner):
        if hasattr(self.model._meta, 'filter_key'):
            return self.filter(**{self.model._meta.filter_key: owner})

ตอนนี้คุณสามารถใช้ SomeModel.objects.get_owned_objs(owner=user1) ในโมเดลที่สืบทอดมาใดๆ ก็ได้ โดยที่ filter_key ถูกตั้งค่าโดยไม่ได้รับชื่อของโมเดล

person Andrey Nelubin    schedule 31.07.2013
comment
ขอบคุณครับ ดูเป็นวิธีแก้ปัญหาที่ดีครับ จะลองดูครับ ฉันยังพบวิธีรับชื่อรุ่นจากผู้จัดการแบบกำหนดเองอีกด้วย ฉันได้อัปเดตคำถามของฉันรวมถึงวิธีแก้ปัญหาของฉันด้วย - person Leonardo; 02.08.2013