Let's say you have a concept of a Battle, and in that battle there are Players and Enemies. The players are a simple ManyToMany, but Enemies require a Through model, because if there's a DB entry for "Goblin", players need to fight an INSTANCE of the Goblin model. Players may fight many Goblins, and each needs their own health/status at any given moment.
So far, I've got a Django model like so (I'm simplifying the code for readability, and to focus on the main issue)
class Battle(models.Model):
players = ManyToMany(Player)
enemies = ManyToMany(Enemy, through=EnemyThroughModel)
With the appropriate adjustments to admin.py and such, this works in that I can attach multiple Enemies to a Battle and see them listed separately in admin, HOWEVER, those are all keyed to the same basic Enemy, and if I change one of them (say, they take damage), ALL the keyed references to that enemy now have their health reduced.
Is there a neat way I can use through models to create a new instance of the enemies, so that they have independent health/mana/etc?
You need to set the health/mana of the enemy within the through model:
class Player(models.Model):
pass
class EnemyType(models.Model):
pass
class EnemyInstance(models.Model):
enemy_type = models.ForeignKey(EnemyType, on_delete=models.CASCADE)
battle = models.ForeignKey('myapp.Battle', on_delete=models.CASCADE)
mana = models.IntegerField()
health = models.IntegerField()
class Battle(models.Model):
players = models.ManyToManyField(Player)
enemies = models.ManyToManyField(EnemyType, through=EnemyInstance)
That being said, relational DBs weren't designed to be used in this manner. You will need to read health/mana stats for players and enemies in real time, while the game in running. It would be better to store this data in memory, using a python object or another data structure (xml, json, etc). See How to choose how to store data? for a good starting point.