class Hero(models.Model):
talents = models.ManyToManyField(Talent)
(...)
class Talent(models.Model)
required_talents = models.ManyToManyField('self', symmetrical=False)
(...)
I would like to create method has_required_talents(self, talent)
for Hero
, which will check if this Hero
has required_talents
for chosen Talent
.
I tried this:
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
However, it doesn't work properly when I test it, using these tests:
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")
What needs to be done to make this work?
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
That would be a list-based approach. You can also convert them to sets:
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
But (I don't know about exact internals, you could run some tests) the first approach should be quicker, because there is no conversion.