Understanding Model Foreign Key Relationship

Hello! I’ve been scratching my head for a while trying to deal with this, it’s really complex to me.
I’m quite new to Django and currently learning how to manage model relationships.
I’ve done the following:
Build a relationship between models based on this:

A User can have a Job Title (Director, Analyst, etc),
and this job title is related to the user’s State and Sector(Who is responsible by X events)

I’ve done the following:

Job Title Class:

class JobTitle(models.Model):
JOB_TITLES = [
(‘0’, ‘Director’),
(‘1’, ‘Manager’),
(‘2’, ‘Coordinator’),
(‘3’, ‘Supervisor’),
(‘4’, ‘Analyst’),
]
jobtitle = models.CharField(max_length=35, choices=JOB_TITLES)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=False, blank=False)
state = models.ForeignKey(States, on_delete=models.SET_NULL, null=True)
sector = models.ForeignKey(Sector, on_delete=models.SET_NULL, null=True)

class Meta:
    verbose_name = "Job Title"
    verbose_name_plural = "Job Titles"

def __str__(self):
    return self.jobtitle

This is the State Class:

class States(models.Model):
states = models.CharField(max_length=100)

def __str__(self) -> str:
    return self.states

class Meta:
    verbose_name_plural = "States"

And the Sector class:

class Sector(models.Model):

sector = models.CharField(max_length=100)
events = models.ManyToManyField(Event)

class Meta:
    verbose_name = "Sector"

def __str__(self) -> str:
    return self.sector

Well, Sectors have many Events related to them, and these Events have many Categories to them

Events Class:

class Event(models.Model):

events = models.CharField(max_length=100)
category = models.ManyToManyField(Category)

def __str__(self):
    return self.events
class Meta:
    verbose_name = "Event"
    verbose_name_plural = "Events"

Categories Class:

class Category(models.Model):

categories = models.CharField(max_length=100)

def __str__(self) -> str:
    return self.categories

class Meta:
    verbose_name = "Category"
    verbose_name_plural = "Categories"

Thing is, i’m trying to build an alarm system where the user needs to register a “trigger” by choosing the Event, Category and State, and apply a logic where i can point to the User with the correct Job Title who is responsible for that State’s Events depending on the time.
The trigger order is: If an event is not solved in 1 hour, it goes to the next tier of triggers.

Example:
The User will choose in what order he wants to be alarmed (T0, T1, etc) and by what Events (With their related Categories)

Kinda goes like this:

The Trigger Order:

class Trigger(models.Model):
TRIGGER_ORDER = [
(‘0’, ‘T0’),
(‘1’, ‘T1’),
(‘2’, ‘T2’),
(‘3’, ‘T3’),
(‘4’, ‘T4’),
(‘5’, ‘T5’),
(‘6’, ‘T6’),
]
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
events = models.ForeignKey(Event, on_delete=models.SET_NULL, null=True)
order = models.CharField(max_length=7, choices=TRIGGER_ORDER)

The Trigger Register Model:

class RegisterTrigger(models.Model):

eventtype = models.ForeignKey('Event', on_delete=models.CASCADE, verbose_name="Event:")
categorytype = models.ForeignKey('Category', on_delete=models.CASCADE, verbose_name="Category:")
statetype = models.ForeignKey('States', on_delete=models.CASCADE, verbose_name="State:")
created_date = models.DateTimeField(auto_now_add=True, verbose_name="Created in")

class Meta:
    verbose_name = "Register Trigger"

Time Logic:

def diff_date_time(self):
    data_event = timezone.localtime(self.data)
    data_current = timezone.localtime(timezone.now())
    diff_hour = (data_current.timestamp() - data_event.timestamp())/3600

    if diff_hour < 1:
        #Get the user who is related to T0
        return data
    elif diff_hour < 2:
        #Get the user who is related to T1
        return data
    elif diff_hour < 3:
        #Get the user who is related to T2
        return data
    elif diff_hour < 4:
        #Get the user who is related to T3
        return data
    elif diff_hour < 5:
        #Get the user who is related to T4
        return data
    elif diff_hour >= 6:
        #Get the user who is related to T5
        return data

I’m sorry for the huge post. How in the programmer’s gods name do i build up such a relationship? Thanks in advance! I managed to display and build filters for the events and categories, but i have no clue at all how to relate all of this. (Also i suck at drawing arrows.)

Questions:

  1. What model instance(s) do you start with when beginning alerting users?

  2. How many job titles can a user hold and how many users can a single job title be assigned to (the combo of title, state and sector)? I ask because I think having a User FK on the JobTitle model is odd. I would have expected it to be in the opposite direction or a ManyToManyField.

Thing is, i’m trying to build an alarm system where the user needs to register a “trigger” by choosing the Event, Category and State

  1. Why is Category listed above?

Unrelated code quality suggestions:

  1. Change Trigger.order to be an IntegerField to make sorting easier on yourself.
  2. Don’t name the name/title field on models the same as the model. For example, State.states and Sector.sector. Eventually you’ll get confused whether you’re referencing the string value or the model instance.
  3. When defining a ManyToManyField, it’s better to use the plural case than singular since when you access it on the model you’re accessing a collection. See Event.category.
  4. Try to be consistent with snake casing. You have a few fields on RegisterTrigger that are all lower case without underscores.

Hey, Tim! Thank you so much for your input and suggestions, I’ll be sure to apply them consistently from now on and will try my best to answer your questions based on my limited knowledge

What model instance(s) do you start with when beginning alerting users?

A: The RegisterTrigger one

How many job titles can a user hold and how many users can a single job title be assigned to (the combo of title, state and sector)? I ask because I think having a User FK on the JobTitle model is odd. I would have expected it to be in the opposite direction or a ManyToManyField.

A: Only one Job Title, and a job title can be assigned to many (There is only one Director, but many Analysts)

Why is Category listed above?

A: You’re right, it is unnecessary. Oopsie

I approach it by fetching the all the Triggers that would match the instance of RegisterTrigger you’re given. From there, order them by priority and then return the first one. When you’re beyond a trigger level, supply that level to exclude those priorities.