How to model an object that has a list of varying types?

I’m working on a site that lets users create “monitors” that let them track the performance of specific computers. They can target computers by their groups, regions, or IP addresses. To make a monitor, there is a form that lets users enter a comma-separated list of targets to monitor and select the type of target. I’m trying to figure out the best way to model this in the database. If this was plain Python, I would write something like this:

@dataclass
class Monitor:
    class Kind(Enum):
        MACHINE_GROUP = auto()
        REGION = auto()
        IP_ADDRESS = auto()
    
    kind: Kind
    targets: list[int] | list[IPv4Address]

With Django, this is the current solution:

class Monitor(models.Model):
    class Kind(models.TextChoices):
        MACHINE_GROUP = "machine_group"
        REGION = "region"
        IP_ADDRESS = "ip_address"

    kind = models.CharField(choices=Kind.choices)

    @property
    def targets(self):
        return self.monitorvalues_set.values_list(self.kind, flat=True)

class MonitorValues(models.Model):
    monitor = models.ForeignKey(Monitor):
    machine_group = models.IntegerField(blank=True, null=True)
    region = models.IntegerField(blank=True, null=True)
    ip_address = models.GenericIPAddressField(protocol="IPv4", blank=True, null=True)

Something in my gut says this could be done better, but I’m not sure how. Could this be done better, or is this actually a good solution?

Facilitating the entry of data is only part of identifying a suitable design. Understanding how this data is going to be used (in specific terms, not general) is as least as important - if not more important, as in many cases the data is going to be read many more times than written.

So you’ll usually want to design your data models around how it’s going to be used, not how it’s going to be entered.

1 Like