Basic understanding of models.py

Hello, I have a basic question about dealing with the models. Let’s assume I have the following models:

Project
System
Department
Employee
Responsibility
Problem
  • System includes the FK from Project.
  • Employee has a many-to-many relationship with Department.
  • A responsibility is a combination of the Project_ID, System_ID, Department_ID and Employee_ID fields.
  • A problem belongs to a responsibility.

What should the model for the problem now look like? Is it enough to use the FK from Responsibility plus my new columns? I could already establish the relationship 100% like this in my opinion. Or do I take all the FK from the Responsibility Model plus the FK for the Responsibility Model itself and my new columns?

For example, I would like to be able to filter all problems for a project in my template. Does this work if you just take the FK out of the responsibility model?

The same applies to the responsibility model itself. The system depends on the project, so do I still need the FK for the project in the model?

Best regards
Patrick

I’m not sure I’m quite following the way you’re expressing usage of foreign keys here.

The common expression of the use of a foreign key is that a model may have a foreign key to another model, you don’t “get” a foreign key from a model.

If this is precisely accurate:

Then yes, having an FK to Responsibility in Problem would be appropriate and sufficient.

This could be created as a model where Responsibility has FKs to all of Project, System, Department, and Employee.

(Side question: Is it true that an Employee may be related to multiple Department? In the “common case”, an Employee is a member of (is related to) a single Department.)

Hi Ken, thank you very much for your comments. I’ll try to explain it a little more precisely. This is my models.py file at the moment. I hope the names are comprehensible to you, they are in German. I can also adjust it if necessary.

from django.db import models


class Projekt(models.Model):
    name = models.CharField(max_length=100, blank=False, null=False, unique=True)
    kostentraeger = models.CharField(max_length=6, blank=False, null=False, unique=True)
    erstellt = models.DateTimeField(auto_now_add=True)
    aktualisiert = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name_plural = 'Projekte'

    def __str__(self):
        return f'{self.kostentraeger} {self.name}'
    
class Baugruppe(models.Model):
    projekt = models.ForeignKey(Projekt, on_delete=models.CASCADE)
    nummer = models.CharField(max_length=4, blank=False, null=False)
    name = models.CharField(max_length=100, blank=False, null=False)
    erstellt = models.DateTimeField(auto_now_add=True)
    aktualisiert = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name_plural = 'Baugruppen'
        constraints = [
            models.UniqueConstraint(fields=['projekt', 'nummer'], name='unique_system')
        ]

    def __str__(self):
        return f'{self.nummer} {self.name}'
    

class Abteilung(models.Model):
    name = models.CharField(max_length=10, blank=False, null=False, unique=True)
    erstellt = models.DateTimeField(auto_now_add=True)
    aktualisiert = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name_plural = 'Abteilungen'

    def __str__(self):
        return self.name
    

class Mitarbeiter(models.Model):
    abteilung = models.ManyToManyField(Abteilung)
    name = models.CharField(max_length=100, blank=False, null=False, unique=True)
    erstellt = models.DateTimeField(auto_now_add=True)
    aktualisiert = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name_plural = 'Mitarbeiter'

    def __str__(self):
        return self.name


class Verantwortlichkeit(models.Model):
    projekt = models.ForeignKey(Projekt, on_delete=models.CASCADE, blank=False, null=False)
    baugruppe = models.ForeignKey(Baugruppe, on_delete=models.CASCADE, blank=False, null=False)
    abteilung = models.ForeignKey(Abteilung, on_delete=models.CASCADE, blank=False, null=True)
    mitarbeiter = models.ForeignKey(Mitarbeiter, on_delete=models.SET_NULL, blank=True, null=True)
    erstellt = models.DateTimeField(auto_now_add=True)
    aktualisiert = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name_plural = 'Verantwortlichkeiten'
        constraints = [
            models.UniqueConstraint(fields=['projekt', 'baugruppe', 'abteilung', 'mitarbeiter'], name='unique_responsibility')
        ]

    def __str__(self):
        return f'{self.projekt} | {self.baugruppe} | {self.abteilung} | {self.mitarbeiter}'


class Problem(models.Model):
    verantwortlichkeit = models.ForeignKey(Verantwortlichkeit, on_delete=models.CASCADE, blank=False, null=False)
    beschreibung = models.TextField(max_length=2000, blank=False, null=False)
    erstellt = models.DateTimeField(auto_now_add=True)
    aktualisiert = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name_plural = 'Probleme'
    
    def __str__(self):
        return f'{self.verantwortlichkeit} | {self.beschreibung}'


class Loesung(models.Model):
    problem = models.ForeignKey(Problem, on_delete=models.CASCADE, blank=False, null=False)
    beschreibung = models.TextField(max_length=2000, blank=False, null=False)
    erstellt = models.DateTimeField(auto_now_add=True)
    aktualisiert = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name_plural = 'Loesungen'

    def __str__(self):
        return f'{self.problem} | {self.beschreibung}'
    

class Status(models.Model):
    projekt = models.ForeignKey(Projekt, on_delete=models.CASCADE, blank=False, null=False)
    baugruppe = models.ForeignKey(Baugruppe, on_delete=models.CASCADE, blank=False, null=False)
    abteilung = models.ForeignKey(Abteilung, on_delete=models.CASCADE, blank=False, null=True)
    mitarbeiter = models.ForeignKey(Mitarbeiter, on_delete=models.SET_NULL, blank=True, null=True)
    FARBEN = (
        ('Rot', 'Rot'),
        ('Gelb', 'Gelb'),
        ('Grün', 'Grün'),
    )
    ampel = models.CharField(max_length=4, choices=FARBEN, blank=False, null=False, default='Grün')
    erstellt = models.DateTimeField(auto_now_add=True)
    aktualisiert = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name_plural = 'Status'

    def __str__(self):
        return self.ampel

Should the model for the status look more like this? Actually, the status also depends on responsibility.

class Status(models.Model):
    verantwortlichkeit = models.ForeignKey(Verantwortlichkeit, on_delete=models.CASCADE, blank=False, null=False)
    #projekt = models.ForeignKey(Projekt, on_delete=models.CASCADE, blank=False, null=False)
    #baugruppe = models.ForeignKey(Baugruppe, on_delete=models.CASCADE, blank=False, null=False)
    #abteilung = models.ForeignKey(Abteilung, on_delete=models.CASCADE, blank=False, null=True)
    #mitarbeiter = models.ForeignKey(Mitarbeiter, on_delete=models.SET_NULL, blank=True, null=True)
    FARBEN = (
        ('Rot', 'Rot'),
        ('Gelb', 'Gelb'),
        ('Grün', 'Grün'),
    )
    ampel = models.CharField(max_length=4, choices=FARBEN, blank=False, null=False, default='Grün')
    erstellt = models.DateTimeField(auto_now_add=True)
    aktualisiert = models.DateTimeField(auto_now=True)

The question is whether my models are so right and efficient or whether you would do it differently. With the foreign keys, I put it somewhat colloquially.

You’re actually right about the department. The requesters call it a department, but it’s actually more of a mix of departments and teams. Therefore, an employee can have multiple entries.

Best regards
Patrick