Question

I have two models in Django for a 2d map based game:

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)

Now I just want associate these two models using ONE table:

class ShopBlockAssoc(models.Model):
    block = models.ForeignKey(Block)
    shop = models.foreignKey(Shop)

After I set the through field in ShopBuilding model, Django yiled multiple fails when syncdb, like

    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'.

If I set db_table field Django says:

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.

How could I fix this? I really want to make sure those shop-block relations are using the sharing the same intermediate associate model with the same db_table

Was it helpful?

Solution

The problem is that on model Block it tries to create backwards links. Django names those links based on Model, in your case for all ManyToMany it tries to create shopbuilding_set and names collide. To avoid this add related_name, for example:

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")

Then you'll be able to access ShopBuilding from Block instance like this:

block.shopbuilding_npc_set.all()

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top