Search code examples
pythondjangomany-to-many

Django: prefetch_related() with m2m through relationship v2


I know there is already a similar question, but I think my case is a bit more complicated because I have a different entry point.

These are my models:

class m_Interaction(models.Model):
  fk_ip = models.ForeignKey('m_IP', related_name="interactions")

class m_User(models.Model):
  name = models.CharField(max_length=200)

class m_IP(models.Model):
  fk_user = models.ForeignKey('m_User', related_name="ips" )

class m_Feature(models.Model):
  name = models.CharField(max_length=200)
  m2m_interaction = models.ManyToManyField(m_Interaction, related_name='features', through='m_Featurescore')

class m_Featurescore(models.Model):
  score = models.FloatField(null=False)
  fk_interaction = models.ForeignKey(m_Interaction, related_name='featurescore')
  fk_feature = models.ForeignKey(m_Feature, related_name='featurescore')

I start with m_User, follow the reverse relationship over m_IP to the Interactions (m_Interaction). Then I want to get every m_Featurescore.score for each Interaction for a specific instance of m_Feature.

My working query to access at least all interactions in a performant way:

m_User.objects.all().prefetch_related('ips__interactions')

But I can't figure out the correct 'prefetch_related'-statement to access the m_Featurescore.score like this

db_obj_interaction.featurescore.get(fk_feature=db_obj_feature).score

without making a lot of queries.

I already tried almost all combinations of the following:

'ips__interactions__features__featurescore'

Any suggestions?


Solution

  • I found the answer to my own question with the help of noamk in the comments:

    I didn't consider that the get()-method in db_obj_interaction.featurescore.get(fk_feature=db_obj_feature).score will issue a new query everytime it's called (it's kinda obvious now).

    Therefore I simply restructured my code and now I don't need get() anymore and can use the benefit of the prefetch.

    If somebody still needs to filter the Prefetch()-object should be used as suggested by noamk