Вопрос
У меня есть две модели в Django для игры на основе 2D-карты:
class Block(models.Model):
type = models.IntegerField()
class ShopBuilding(models.Model):
house_blocks = models.ManyToManyField(Block)
street_blocks = models.ManyToManyField(Block)
river_blocks = models.ManyToManyField(Block)
decoration_blocks = models.ManyToManyField(Block)
npc_blocks = models.ManyToManyField(Block)
Теперь я просто хочу связать эти две модели, используя ОДНУ таблицу:
class ShopBlockAssoc(models.Model):
block = models.ForeignKey(Block)
shop = models.foreignKey(Shop)
После того, как я установил through
поле в ShopBuilding
модель, Django выдал несколько ошибок при синхронизации базы данных, например
Error: One or more models did not validate:
tnew.shopbuilding: Accessor for m2m field 'house_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'house_blocks'.
tnew.shopbuilding: Accessor for m2m field 'house_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'house_blocks'.
tnew.shopbuilding: Accessor for m2m field 'house_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'house_blocks'.
tnew.shopbuilding: Accessor for m2m field 'house_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'house_blocks'.
tnew.shopbuilding: Accessor for m2m field 'street_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'street_blocks'.
tnew.shopbuilding: Accessor for m2m field 'street_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'street_blocks'.
tnew.shopbuilding: Accessor for m2m field 'street_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'street_blocks'.
tnew.shopbuilding: Accessor for m2m field 'street_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'street_blocks'.
tnew.shopbuilding: Accessor for m2m field 'river_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'river_blocks'.
tnew.shopbuilding: Accessor for m2m field 'river_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'river_blocks'.
tnew.shopbuilding: Accessor for m2m field 'river_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'river_blocks'.
tnew.shopbuilding: Accessor for m2m field 'river_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'river_blocks'.
tnew.shopbuilding: Accessor for m2m field 'decoration_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'decoration_blocks'.
tnew.shopbuilding: Accessor for m2m field 'decoration_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'decoration_blocks'.
tnew.shopbuilding: Accessor for m2m field 'decoration_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'decoration_blocks'.
tnew.shopbuilding: Accessor for m2m field 'decoration_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'decoration_blocks'.
tnew.shopbuilding: Accessor for m2m field 'npc_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'npc_blocks'.
tnew.shopbuilding: Accessor for m2m field 'npc_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'npc_blocks'.
tnew.shopbuilding: Accessor for m2m field 'npc_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'npc_blocks'.
tnew.shopbuilding: Accessor for m2m field 'npc_blocks' clashes with related m2m field 'Block.shopbuilding_set'. Add a related_name argument to the definition for 'npc_blocks'.
Если я установлю db_table
поле Джанго говорит:
The model has two manually-defined m2m relations through the model, which is not permitted. Please consider using an extra field on your intermediary model instead.
Как я могу это исправить?Я действительно хочу убедиться, что эти отношения цех-блок используют одну и ту же промежуточную ассоциированную модель с одной и той же db_table.
Решение
Проблема в том, что на модели Block
он пытается создать обратные ссылки.Джанго называет эти ссылки на основе модели, в вашем случае для всех ManyToMany, которые он пытается создать. shopbuilding_set
и имена сталкиваются.Чтобы избежать этого, добавьте related_name
, например:
class ShopBuilding(models.Model):
house_blocks = models.ManyToManyField(Block, related_name="shopbuilding_house_set")
street_blocks = models.ManyToManyField(Block, related_name="shopbuilding_street_set")
river_blocks = models.ManyToManyField(Block, related_name="shopbuilding_river_set")
decoration_blocks = models.ManyToManyField(Block, related_name="shopbuilding_decoration_set")
npc_blocks = models.ManyToManyField(Block, related_name="shopbuilding_npc_set")
Тогда вы сможете получить доступ ShopBuilding
от Block
например такой:
block.shopbuilding_npc_set.all()