0

A little confused on how to do join's in Django.

For example I have the following 3 tables:

battlefield_weakresistimmune;
 id | weakResistanceImmune | multiplier | pokemon_id | typing_id
----+----------------------+------------+------------+-----------

battlefield_basepokemontest;
 id |     name      | base_hp | base_atk | base_def | base_spatk | base_spdef | base_speed |  ability1  | ability2  | hidden_ability | pokemon_id | type1_id | type2_id | type3_id
----+---------------+---------+----------+----------+------------+------------+------------+------------+-----------+----------------+------------+----------+----------+----------
  1 | Bulbasaur     |      45 |       49 |       49 |         65 |         65 |         45 | Overgrowth | n/a       | Chlorophyll    |          1 |       12 |        4 |
  2 | Ivysaur       |      60 |       62 |       63 |         80 |         80 |         60 | Overgrowth | n/a       | Chlorophyll    |          2 |       12 |        4 |


battlefield_pokemontypestest;
 id |   name
----+----------
  1 | Normal
  2 | Fighting
  3 | Flying
  4 | Poison

I want to get the name of the Pokemon from basepokemontest, the condition and multiplier from weakresistimmune and the type name from pokemontypestest.

I can easily do that in SQL via:

SELECT poke.name, con.weak_resist_immune, type.name, con.multiplier FROM battlefield_basepokemontest poke INNER JOIN battlefield_weakresistimmune con ON poke.id = con.pokemon_id INNER JOIN battlefield_pokemontypestest type ON type.id = con.typing_id;
   name    | weak_resist_immune |  name  | multiplier
-----------+--------------------+--------+------------
 Bulbasaur | Weak               | Flying |       2.00

I read some docs and tried to chain filters, but doesn't seem to be working.

Is chaining filters the correct method to do a join in django or am i missing something?

*** EDIT *** Hi all, sorry was a little busy yesterday. My models look like this, minus the methods:

class PokemonTypesTest(models.Model):
    name = models.CharField(max_length=25, unique=True)

    def __str__(self):
        return self.name 

class BasePokemonTest(models.Model):
    name = models.CharField(max_length=50, unique=True)
    base_hp = models.IntegerField()
    base_atk = models.IntegerField()
    base_def = models.IntegerField()
    base_spatk = models.IntegerField()
    base_spdef = models.IntegerField()
    base_speed = models.IntegerField()
    type1 = models.ForeignKey(PokemonTypesTest, null=True, on_delete=models.SET_NULL, related_name='pokemontype1')
    type2 =  models.ForeignKey(PokemonTypesTest, null=True, on_delete=models.SET_NULL, related_name='pokemontype2')
    type3 =  models.ForeignKey(PokemonTypesTest, null=True, on_delete=models.SET_NULL, related_name='pokemontype3')
    ability1 = models.CharField(max_length=25, default='n/a') #these abilities (ability1, ability2 and hidden_ability will need to be moved to a many-to-many table)
    ability2 = models.CharField(max_length=25, default='n/a') #where a pokemon id from basepokemon table is linked to a ability id
    hidden_ability = models.CharField(max_length=40, default='n/a')
    pokemon_id = models.IntegerField(default=0)


    weakness_resistance_immune = models.ManyToManyField(PokemonTypesTest, through='WeakResistImmune')

class WeakResistImmune(models.Model):
    #in the typing field, 1 is weakness
    pokemon = models.ForeignKey(BasePokemonTest, on_delete=models.CASCADE)
    weak_resist_immune = models.CharField(max_length=25)
    typing = models.ForeignKey(PokemonTypesTest, on_delete=models.CASCADE)
    multiplier = models.DecimalField(max_digits=5, decimal_places=2)

I tried the following to achieve the SQL query I did in postgresql, but with django:

 dataSet = WeakResistImmune.objects.select_related('pokemon','typing').all()

It returns a query list where I can get the result I want:

>>> for i in dataSet:
...     print(str(i.pokemon.name) + ' is ' + str(i.weak_resist_immune) + ' to ' + i.typing.name + ' by a multiplier of ' + str(i.multiplier))
...
Bulbasaur is Weak to Flying by a multiplier of 2.00
Bulbasaur is Weak to Fire by a multiplier of 2.00
Bulbasaur is Weak to Psychic by a multiplier of 2.00
Bulbasaur is Weak to Ice by a multiplier of 2.00
Bulbasaur is Resist to Fighting by a multiplier of 0.50
Bulbasaur is Resist to Water by a multiplier of 0.50
Bulbasaur is Resist to Grass by a multiplier of 0.25
Bulbasaur is Resist to Electric by a multiplier of 0.50
Bulbasaur is Resist to Fairy by a multiplier of 0.50

Now I'm a bit confused if I should do it the way I have to achieve my result, or if I was supposed to use prefetch_related on the many-to-many field in BasePokemonTest called weakness_resistance_immune = models.ManyToManyField(PokemonTypesTest, through='WeakResistImmune')

Any thoughts on if I did it correct?

*** EDIT 2 ***

Found and set up this django debug tool, that shows me the queries. Looks like the select_related does what I want in this case while only sending 1 query!

The following is what came back.

SELECT ••• FROM "battlefield_weakresistimmune" INNER JOIN "battlefield_basepokemontest" ON ("battlefield_weakresistimmune"."pokemon_id" = "battlefield_basepokemontest"."id") INNER JOIN "battlefield_pokemontypestest" ON ("battlefield_weakresistimmune"."typing_id" = "battlefield_pokemontypestest"."id") LIMIT 21
jarjarbinks99
  • 165
  • 1
  • 7

0 Answers0