【问题标题】:Django: How to check if object with ManyToManyField contains the entire contents of other object ManyToManyField?Django:如何检查具有 ManyToManyField 的对象是否包含其他对象 ManyToManyField 的全部内容?
【发布时间】:2012-11-01 12:07:10
【问题描述】:
class Hero(models.Model):
   talents = models.ManyToManyField(Talent)
   (...)

class Talent(models.Model)
   required_talents = models.ManyToManyField('self', symmetrical=False)
   (...)

我想为Hero 创建方法has_required_talents(self, talent),它将检查这个Hero 是否有required_talents 用于选择的Talent

我试过了:

def has_required_talents(self, talent)
   required_list = talent.talents_required.values_list('id', flat=True)
   hero_talents = self.hero.talents.values_list('id', flat=True)
   if required_list in hero_talents:
      return True
   return False

但是,当我使用以下测试对其进行测试时,它无法正常工作:

class HeroTalents(TestCase):
 def setUp(self):
    self.hero=Hero('Duck')
    self.hero.save() 

 def test_has_required_talents(self):
    self.talent1 = Talent(name = "Overpower")
    self.talent1.save()
    self.talent2 = Talent(name = "Overpower2")
    self.talent2.save()
    self.talent2.talents_required.add(self.talent1)
    self.assertFalse(self.hero.has_required_talents(self.talent2), "test1")
    self.hero.talents.add(self.talent1)
    self.assertTrue(self.hero.has_required_talents(self.talent2), "test2")
    self.talent3 = Talent(name = "Overpower3")
    self.talent3.save()
    self.hero.talents.add(self.talent2)
    self.assertTrue(self.hero.has_required_talents(self.talent3), "test3")
    self.talent1.talents_required.add(self.talent3)
    self.assertFalse(self.hero.has_required_talents(self.talent1), "test4")

需要做些什么来完成这项工作?

【问题讨论】:

    标签: python django django-models many-to-many


    【解决方案1】:
    def has_required_talents(self, talent)
       required_list = talent.talents_required.values_list('id', flat=True)
       hero_talents = self.hero.talents.values_list('id', flat=True)
       for item in required_list:
          if not item in hero_talents:
             return False
       return True
    

    这将是一种基于列表的方法。您还可以将它们转换为集合:

    def has_required_talents(self, talent)
       required_list = set(talent.talents_required.values_list('id', flat=True))
       hero_talents = set(self.hero.talents.values_list('id', flat=True))
       if required_list.issubset(hero_talents):
          return True
       return False
    

    但是(我不知道确切的内部结构,你可以运行一些测试)第一种方法应该更快,因为没有转换。

    【讨论】:

    • 恐怕它没有通过test1(你可以在第一篇文章中看到test)。
    • 好吧,因为 Talent1 有空的 Talent_required 关系,所以函数显然返回 true。在这种情况下你为什么想要一个假的?
    • 你是对的。现在问题中添加了正确的测试,并且您的代码一切正常。谢谢它对我帮助很大。无论如何,我检查了第一种和第二种方法,它只适用于集合。第一种方法没有通过test2。你能告诉我为什么吗?
    • 抱歉,我不小心没有将 required_list 更改为 if 中的项目。现在它应该可以正常工作了 :) 很高兴为您提供帮助!
    猜你喜欢
    • 2017-10-09
    • 1970-01-01
    • 2013-06-11
    • 2021-10-30
    • 2019-08-10
    • 2020-04-25
    • 2020-04-22
    • 1970-01-01
    • 2016-02-05
    相关资源
    最近更新 更多