There are a lot of questions along these lines, but so far as I can tell, but many are quite old and I haven't found one that helped me understand my use case. I think I want to be looking at signals, but I'm not clear on exactly what I should be doing in terms of Django patterns and best practices.
from django.db import models
from django.db.models.fields import SlugField, TextField
from django.utils import timezone
# Hexes have Terrains, which impart intrinsic properties, like base speed and .png image
# They're NOT 1:1 with Hexes IE) You might want Slow and Normal Grasslands with the same image
class Terrain(models.Model):
FAST = 'F'
NORMAL = 'N'
SLOW = 'S'
SPEED_CHOICES = [
(FAST, 'Fast'),
(NORMAL, 'Normal'),
(SLOW, 'Slow'),
]
name = models.CharField(max_length=64)
speed = models.CharField(max_length=6, choices=SPEED_CHOICES, default=NORMAL)
image = models.ImageField(upload_to='images/', blank=True)
def __str__(self):
return self.name
# Grids establish the dimensions of a HexMap. Grids may be used in many HexMaps
class Grid(models.Model):
name = models.CharField(max_length=64)
size = models.IntegerField(default=72)
num_rows = models.IntegerField(default=10)
num_cols= models.IntegerField(default=10)
def __str__(self):
return self.name
# Hexes represent the "tiles" on a Grid. A single Hex may appear in many Grids
class Hex(models.Model):
name = models.CharField(max_length=64, blank=True, null=True)
terrain = models.ForeignKey(Terrain, on_delete=models.CASCADE)
grids = models.ManyToManyField(Grid)
def __str__(self):
return self.id
class Meta:
verbose_name_plural = "Hexes"
# Locations are coordinal points on a HexMap. They may contain many Annotations
class Location(models.Model):
# HexMap Name + row + col, for a consistent way to ID locations
name = models.CharField(max_length=64, blank=True, null=True)
friendly_name = models.CharField(max_length=64, blank=True, null=False)
# TODO constrain these to the sizes specified in the grids? Sane defaults?
row = models.PositiveIntegerField()
col = models.PositiveIntegerField()
# Authors create Annotations
# TODO create Players and make Authors extend it so we can do rights and perms
class Author(models.Model):
first_name = models.CharField(max_length=64, blank=False, null=False)
last_name = models.CharField(max_length=64, blank=False, null=False)
join_date = timezone.now()
def __str__(self):
return self.first_name + " " + self.last_name
# Annotations are entries created by Authors. A location may have many Annotations
class Annotation(models.Model):
name = models.CharField(max_length=64, blank=False, null=False)
pubdate = join_date = timezone.now()
content = TextField()
# Hexmaps put it all together and allow fetching of Locations by (r,c) coords
class HexMap(models.Model):
name = models.CharField(max_length=64, blank=True, null=True)
rows = {}
cols = {}
#TODO - how do I create grid.num_rows * grid.num_cols locations and put them into the dicts?
I am probably making a ton of mistakes as I've not worked in Django in close to a decade. Any constructive feedback is appreciated in the comments. Most of the relationships are not coded in, as I'm not sure how they should look.
My specific question, however, is related the HexMap and Location objects.
When a HexMap is created, I want to create a set of empty Locations with a default name value matching a naming convention like HexMap.name + row + col
and fill the row{} and col{} dicts of the new HexMap with them.
My instinct is that a Hexmap needs a Grid in order to be created, so I could create a nested loop inside HexMap with grid.num_rows as as the outer loop and num_cols as the inner loop. Each iteration through the inner loop builds a row of Locations as a dict. Each iteration of the outer loop adds that row to the rows{} dict. One thing I'm not certain about is how I'd get the grid.num_rows and grid.num_cols when the HexMap isn't even created yet, and doesn't have a grid associated.
Is this anywhere near the right way to do this in Django, or am I off the mark? Many of the answers and online tutorials seem to indicate that I need to look at signals, but I'm just not really clear on whether or not that's the case. Also, if so, I could use some similar examples to review. The Django docs are great and helpful, but when you're "new" to it all, it can be hard to parse and adopt the examples.