Trying to find out the best way to model my data.
I have one table for pokemon types:
class PokemonTypesTest2(models.Model):
name = models.CharField(max_length=25, unique=True)
It just has an ID and name, it will have 18 rows in it. I want to be able to relate multiple tables to it, for example base Pokemon model below ( i cleared out most of the data to be easier to follow:
class BasePokemonTest2(models.Model):
#other data hidden #
type1 = models.ForeignKey(PokemonTypesTest2, on_delete=models.CASCADE, default=1)
type2 = models.ForeignKey(PokemonTypesTest2, on_delete=models.CASCADE, default=1)
type3 = models.ForeignKey(PokemonTypesTest2, on_delete=models.CASCADE, default=1)
weaknessResistanceImmune = models.ManyToManyField(PokemonTypesTest2, through='WeakResistImmune2')
I want to be able to relate a pokemon typing to a pokemon from base pokemon table.
The problem is I get this error from Django:
ERRORS:
battlefield.BasePokemonTest2.type1: (fields.E304) Reverse accessor 'PokemonTypesTest2.basepokemontest2_set' for 'battlefield.BasePokemonTest2.type1' clashes with reverse accessor for 'battlefield.BasePokemonTest2.type2'.
HINT: Add or change a related_name argument to the definition for 'battlefield.BasePokemonTest2.type1' or 'battlefield.BasePokemonTest2.type2'.
I see the hint but don't understand what it means?
CodePudding user response:
With a ForeignKey, If you do not override the default by specifying an argument of "related_name" then Django will use a name made up from the source model name (PokemonTypesTest2) lowercased and appended with "_set". This gives you access to a Manager that returns all instances of PokemonTypesTest2 related to your BasePokemonTest2 instance. e.g.
>>> p = BasePokemonTest2.objects.get(id=1)
>>> p.pokemontypestest2_set.all() # Returns all PokemonTypesTest2 objects related to BasePokemonTest2 instance
Django Docs: Following Relationships "backward"
So your type1, type2 and type3 assignments in your BasePokemonTest2 model are all attempting to have a name of "basepokemontest2_set". This is not allowed as each related_name (in one model definition) has to be unique of course. Hence the hint from Django recommending you use related_name to resolve the clash.
So, to work as you wanted in your code above, you would need something like:
type1 = models.ForeignKey(PokemonTypesTest2, on_delete=models.CASCADE, default=1, related_name="type1")
type2 = models.ForeignKey(PokemonTypesTest2, on_delete=models.CASCADE, default=1, related_name="type2")
type3 = models.ForeignKey(PokemonTypesTest2, on_delete=models.CASCADE, default=1, related_name="type3")
However, I don't think this is really what you want? I suspect you probably just want:
type = models.ForeignKey(PokemonTypesTest2, on_delete=models.CASCADE, default=1)
(You can also still add related_name above (setting it to whatever you want) if you don't want the default _set name.)
You can then access all PokemonTypesTest2 related to one BasePokemonTest2 as mentioned above.