To make it even clearer, I have once again reset my code to the most essential.
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.responsibilities_overview, name='responsibilities-overview'),
path('responsibility-details/<int:id>/', views.responsibility_details, name='responsibility-details'),
path('problem-create/', views.problem_create, name='problem-create'),
path('problem-update/<int:id>/', views.problem_update, name='problem-update'),
]
views.py:
from django.shortcuts import render, get_object_or_404
from .models import Responsibility, BottleneckPart, Drawing, Meeting
from .filters import ResponsibilityFilter, DrawingFilter
# Create your views here.
def responsibilities_overview(request):
responsibilities = Responsibility.objects.all()
responsibilities_filter = ResponsibilityFilter(request.GET, queryset=responsibilities)
responsibilities = responsibilities_filter.qs
context = {'responsibilities': responsibilities, 'responsibilities_filter': responsibilities_filter}
return render(request, 'systemcockpit/responsibilities_overview.html', context)
def responsibility_details(request, id):
responsibility = get_object_or_404(Responsibility, id=id)
bottleneck_parts = BottleneckPart.objects.filter(cost_bearer=responsibility.project.cost_bearer).filter(department=responsibility.team.department.name). \
filter(system=responsibility.system.number)
drawings = Drawing.objects.filter(cost_bearer=responsibility.project.cost_bearer).filter(department=responsibility.team.department.name). \
filter(system=responsibility.system.number).order_by('drawing_number').values()
drawings_filter = DrawingFilter(request.GET, queryset=drawings)
drawings = drawings_filter.qs
drawings_visibility = Drawing.objects.filter(cost_bearer=responsibility.project.cost_bearer).filter(department=responsibility.team.department.name). \
filter(system=responsibility.system.number).order_by('drawing_number').values()
project_rounds = Meeting.objects.filter(cost_bearer=responsibility.project.cost_bearer).filter(system=responsibility.system.number). \
filter(title='Projektrunde').order_by('description', 'subject', 'item', 'date', 'responsibility').values()
working_meetings = Meeting.objects.filter(cost_bearer=responsibility.project.cost_bearer).filter(system=responsibility.system.number). \
filter(title='Working Meeting').order_by('description', 'subject', 'item', 'date', 'responsibility').values()
context = {'responsibility': responsibility, 'bottleneck_parts': bottleneck_parts, 'drawings': drawings \
, 'project_rounds': project_rounds, 'working_meetings': working_meetings, 'drawings_filter': drawings_filter \
, 'drawings_visibility': drawings_visibility}
return render(request, 'systemcockpit/responsibility_details.html', context)
def problem_create(request):
# ProblemForm
context = {}
return render(request, 'systemcockpit/problem_form.html', context)
def problem_update(request, id):
# ProblemForm
context = {}
return render(request, 'systemcockpit/problem_form.html', context)
The two views problem_create and problem_update are only intended to serve as a shell, so that you know what I’m up to.
models.py:
class Responsibility(models.Model):
COLORS = (
('Rot', 'Rot'),
('Gelb', 'Gelb'),
('Grün', 'Grün'),
)
project = models.ForeignKey(Project, on_delete=models.CASCADE, verbose_name='Projekt')
system = models.ForeignKey(System, on_delete=models.CASCADE, verbose_name='Baugruppe')
team = models.ForeignKey(Team, on_delete=models.CASCADE, verbose_name='Team')
employee = models.ForeignKey(Employee, on_delete=models.SET_NULL, blank=True, null=True, verbose_name='Mitarbeiter')
traffic_light = models.CharField(max_length=4, choices=COLORS, default='Grün', verbose_name='Status')
created_at = models.DateTimeField(auto_now_add=True, editable=False, blank=True, verbose_name='Erstelldatum')
updated_at = models.DateTimeField(auto_now=True, editable=False, blank=True, verbose_name='Änderungsdatum')
user = models.ForeignKey('auth.User', on_delete=models.SET_DEFAULT, default=1, editable=False, verbose_name='Ersteller / Änderer')
class Meta:
verbose_name = 'Verantwortlichkeit'
verbose_name_plural = 'Verantwortlichkeiten'
constraints = [
models.UniqueConstraint(fields=['project', 'system', 'team', 'employee'], name='uq_project_system_team_employee')
]
def __str__(self):
return f'{self.project} | {self.system} | {self.team} | {self.employee} | {self.traffic_light}'
class Problem(models.Model):
responsibility = models.ForeignKey(Responsibility, on_delete=models.CASCADE, verbose_name='Verantwortlichkeit', related_name='problems')
summary = models.CharField(max_length=150, verbose_name='Zusammenfassung')
description = models.TextField(verbose_name='Beschreibung')
created_at = models.DateTimeField(auto_now_add=True, editable=False, blank=True, verbose_name='Erstelldatum')
updated_at = models.DateTimeField(auto_now=True, editable=False, blank=True, verbose_name='Änderungsdatum')
user = models.ForeignKey('auth.User', on_delete=models.SET_DEFAULT, default=1, editable=False, verbose_name='Ersteller / Änderer')
class Meta:
verbose_name = 'Problem'
verbose_name_plural = 'Probleme'
def __str__(self):
return f'{self.responsibility} | {self.summary}'
class Solution(models.Model):
problem = models.OneToOneField(Problem, on_delete=models.CASCADE, verbose_name='Problem', related_name='solutions')
summary = models.CharField(max_length=150, verbose_name='Zusammenfassung')
description = models.TextField(verbose_name='Beschreibung')
created_at = models.DateTimeField(auto_now_add=True, editable=False, blank=True, verbose_name='Erstelldatum')
updated_at = models.DateTimeField(auto_now=True, editable=False, blank=True, verbose_name='Änderungsdatum')
user = models.ForeignKey('auth.User', on_delete=models.SET_DEFAULT, default=1, editable=False, verbose_name='Ersteller / Änderer')
class Meta:
verbose_name = 'Maßnahme'
verbose_name_plural = 'Maßnahmen'
def __str__(self):
return f'{self.problem} | {self.summary}'
forms.py:
from django import forms
from .models import Problem
class ProblemForm(forms.ModelForm):
class Meta:
model = Problem
fields = ['responsibility', 'summary', 'description', 'user']
widgets = {
'responsibility': forms.HiddenInput(),
'user': forms.HiddenInput(),
}
responsibility_details.html (relevant part line 44):
{% extends 'base.html' %}
{% load widget_tweaks %}
{% block content %}
{% include 'systemcockpit/includes/navbar.html' %}
<!-- START: Header -->
<div class="container-fluid mt-5 px-5 table-responsive">
<table class="table table-light table-bordered m-0">
<thead>
<tr class="table-primary text-uppercase">
<th>Projekt</th>
<th>Baugruppe</th>
<th>Team</th>
<th>Sektion</th>
<th>Mitarbeiter</th>
<th>Zuletzt aktualisiert</th>
<th class="text-center">Status</th>
</tr>
</thead>
<tbody class="table-group-divider">
<tr>
<td>{{ responsibility.project.cost_bearer }}</td>
<td>{{ responsibility.system }}</td>
<td>{{ responsibility.team }}</td>
<td>Sektion</td>
<td>{{ responsibility.employee|default_if_none:'' }}</td>
<td>XX.XX.2025</td>
{% if responsibility.traffic_light == 'Rot' %}
<td class="text-center"><i class="fa fa-circle" style="font-size:20px; color:red;"></i></td>
{% elif responsibility.traffic_light == 'Gelb' %}
<td class="text-center"><i class="fa fa-circle" style="font-size:20px; color:yellow;"></i></td>
{% else %}
<td class="text-center"><i class="fa fa-circle" style="font-size:20px; color:green;"></i></td>
{% endif %}
</tr>
</tbody>
</table>
</div>
<!-- END: Header -->
<a href="{% url 'problem-create' %}">Problem create</a>
<!-- START: Problem / solutions -->
{% if responsibility.problems.all %}
<div class="container-fluid mt-5 px-5">
<div class="card rounded-0">
<div class="card-header bg-primary text-white fw-bold fst-italic rounded-0"><i class="fa fa-triangle-exclamation pe-2"></i> Probleme / Maßnahmen</div>
<div class="card-body">
<div id="accordion">
{% for problem in responsibility.problems.all %}
<div class="card rounded-0">
<div class="card-header" id="heading{{ forloop.counter }}">
<h5 class="mb-0">
<button class="btn btn-link text-primary px-0" data-bs-toggle="collapse" data-bs-target="#collapse{{ forloop.counter }}" aria-expanded="false" aria-controls="collapse{{ forloop.counter }}">
{% if problem.solution.summary %}
<b>#{{ forloop.counter }} Problem: {{ problem.summary }} ----- Maßnahme: {{ problem.solution.summary }}</b>
{% else %}
<b>#{{ forloop.counter }} Problem: {{ problem.summary }}</b>
{% endif %}
</button>
</h5>
</div>
<div id="collapse{{ forloop.counter }}" class="collapse" aria-labelledby="heading{{ forloop.counter }}" data-bs-parent="#accordion">
<div class="card-body">
<div class="row">
<div class="col-sm-6 mb-3 mb-sm-0">
<div class="card text-dark bg-danger bg-opacity-10 rounded-0">
<div class="card-header">
<b>{{ problem.updated_at|date:'SHORT_DATE_FORMAT' }} {{ problem.user }} - {{ problem.summary }}</b>
</div>
<div class="card-body">
<p class="card-text">{{ problem.description }}</p>
</div>
</div>
</div>
<div class="col-sm-6">
{% if problem.solution %}
<div class="card text-dark bg-success bg-opacity-10 rounded-0">
<div class="card-header">
<b>{{ problem.solution.updated_at|date:'SHORT_DATE_FORMAT' }} {{ problem.solution.user }} - {{ problem.solution.summary }}</b>
</div>
<div class="card-body">
<p class="card-text">{{ problem.solution.description }}</p>
</div>
</div>
{% else %}
<div class="d-grid">
<button class="btn btn-primary text-white" type="button">Maßnahme erstellen</button>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<br />
{% endfor %}
</div>
</div>
</div>
</div>
{% endif %}
<!-- END: Problems / solutuions -->
<!-- START: Bottleneck parts -->
{% if bottleneck_parts %}
<div class="container-fluid mt-5 px-5">
<div class="card rounded-0">
<div class="card-header bg-primary text-white fw-bold fst-italic rounded-0"><i class="fa fa-cart-shopping pe-2"></i> Status Beschaffung</div>
<div class="card-body">
<div class="container-fluid p-0 table-responsive">
<table class="table table-light table-striped table-bordered">
<thead>
<tr class="text-uppercase">
<th class="table-primary">RM-Nr.</th>
<th class="table-primary">Kopfbezeichnung</th>
<th class="table-primary">Pos</th>
<th class="table-primary">Bezeichnung</th>
<th class="table-primary">Pos Status</th>
<th class="table-info">Anfrage an KM Soll</th>
<th class="table-info">Anfrage an KM Ist</th>
<th class="table-danger">Bestellanf. an TP Soll</th>
<th class="table-danger">Bestellanf. an TP Ist</th>
<th class="table-success">Bestellung fertig Soll</th>
<th class="table-success">Bestellung fertig Ist</th>
<th class="table-dark">TU</th>
<th class="table-dark">TU Termin</th>
<th class="table-warning">Lieferzeit AT</th>
<th class="table-warning">Liefertermin Soll</th>
</tr>
</thead>
<tbody class="table-group-divider">
{% for bottleneck_part in bottleneck_parts %}
<tr>
<td>{{ bottleneck_part.feedback_number|default_if_none:'' }}</td>
<td>{{ bottleneck_part.description_head|default_if_none:'' }}</td>
<td>{{ bottleneck_part.position|default_if_none:'' }}</td>
<td>{{ bottleneck_part.description|default_if_none:'' }}</td>
<td>{{ bottleneck_part.po_position_status|default_if_none:'' }}</td>
<td>{{ bottleneck_part.inquiry_purchase_target|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ bottleneck_part.inquiry_purchase_current|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ bottleneck_part.purchase_requisition_planning_target|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ bottleneck_part.purchase_requisition_planning_current|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ bottleneck_part.po_finished_target|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ bottleneck_part.po_finished_current|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ bottleneck_part.technical_document|default_if_none:'' }}</td>
<td>{{ bottleneck_part.technical_document_date|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ bottleneck_part.delivery_time_current|default_if_none:'' }}</td>
<td>{{ bottleneck_part.delivery_date_target|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endif %}
<!-- END: Bottleneck parts -->
<!-- START: Project rounds -->
{% if project_rounds %}
<div class="container-fluid mt-5 px-5">
<div class="card rounded-0">
<div class="card-header bg-primary text-white fw-bold fst-italic rounded-0"><i class="fa fa-list pe-2"></i> Protokoll Projektrunden</div>
<div class="card-body">
<button class="btn btn-primary my-3" type="button" data-bs-toggle="collapse" data-bs-target="#collapseProjectRounds" aria-expanded="false" aria-controls="collapseProjectRounds">
Daten ein- / ausblenden
</button>
<div class="collapse" id="collapseProjectRounds">
<div class="container-fluid p-0 table-responsive">
<table class="table table-light table-striped table-bordered">
<thead>
<tr class="table-primary text-uppercase">
<th>Runde</th>
<th>Punkt</th>
<th>Datum</th>
<th>Bezeichnung</th>
<th>Betreff</th>
<th>Beitrag</th>
<th>Zuständigkeit</th>
<th>Status</th>
<th>Termin</th>
</tr>
</thead>
<tbody class="table-group-divider">
{% for project_round in project_rounds %}
<tr>
<td>{{ project_round.running_number|default_if_none:'' }}</td>
<td>{{ project_round.item|default_if_none:'' }}</td>
<td>{{ project_round.date|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ project_round.description|default_if_none:'' }}</td>
<td>{{ project_round.subject|default_if_none:'' }}</td>
<td>{{ project_round.article|default_if_none:'' }}</td>
<td>{{ project_round.responsibility|default_if_none:'' }}</td>
<td>{{ project_round.status|default_if_none:'' }}</td>
<td>{{ project_round.appointment|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- END: Project rounds -->
<!-- START: Working meetings -->
{% if working_meetings %}
<div class="container-fluid mt-5 px-5">
<div class="card rounded-0">
<div class="card-header bg-primary text-white fw-bold fst-italic rounded-0"><i class="fa fa-list pe-2"></i> Protokoll Working Meetings</div>
<div class="card-body">
<button class="btn btn-primary text-white my-3" type="button" data-bs-toggle="collapse" data-bs-target="#collapseWorkingMeetings" aria-expanded="false" aria-controls="collapseWorkingMeetings">
Daten ein- / ausblenden
</button>
<div class="collapse" id="collapseWorkingMeetings">
<div class="container-fluid p-0 table-responsive">
<table class="table table-light table-striped table-bordered">
<thead>
<tr class="table-primary text-uppercase">
<th>Runde</th>
<th>Punkt</th>
<th>Datum</th>
<th>Bezeichnung</th>
<th>Betreff</th>
<th>Beitrag</th>
<th>Zuständigkeit</th>
<th>Status</th>
<th>Termin</th>
</tr>
</thead>
<tbody class="table-group-divider">
{% for working_meeting in working_meetings %}
<tr>
<td>{{ working_meeting.running_number|default_if_none:'' }}</td>
<td>{{ working_meeting.item|default_if_none:'' }}</td>
<td>{{ working_meeting.date|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ working_meeting.description|default_if_none:'' }}</td>
<td>{{ working_meeting.subject|default_if_none:'' }}</td>
<td>{{ working_meeting.article|default_if_none:'' }}</td>
<td>{{ working_meeting.responsibility|default_if_none:'' }}</td>
<td>{{ working_meeting.status|default_if_none:'' }}</td>
<td>{{ working_meeting.appointment|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- END: Working meetings -->
<!-- START: Drawings -->
{% if drawings_visibility %}
<div class="container-fluid mt-5 px-5" id="status-drawings">
<div class="card rounded-0">
<div class="card-header bg-primary text-white fw-bold fst-italic rounded-0"><i class="fa fa-object-group pe-2"></i> Status d.3</div>
<div class="card-body">
<div class="container-fluid my-3 p-0">
<form action="#status-drawings" method="GET">
<div class="row w-50">
{% for field in drawings_filter.form %}
<div class="col fw-bold">
{{ field.label_tag }}
{% render_field field class="form-control form-control" %}
</div>
{% endfor %}
<div class="col align-self-end">
<button class="btn btn-primary text-white" type="submit">Filtern <i class="fa fa-filter"></i></button>
<a href="{% url 'responsibility-details' responsibility.id %}#status-drawings" class="btn btn-danger">Zurücksetzen <i class="fa fa-times-circle"></i></a>
</div>
</div>
</form>
</div>
<div class="container-fluid p-0 table-responsive">
<table class="table table-light table-striped table-bordered">
<thead>
<tr class="table-primary text-uppercase">
<th>Zeichnungsnummer</th>
<th>Zeichnungsname</th>
<th>Zeichnungsart</th>
<th>Einreichungs Soll</th>
<th>Ende Soll</th>
<th>An AV Soll</th>
<th>Forecast / Prognose</th>
<th>Bearbeitungsstatus</th>
<th>Genehmigungsstatus</th>
</tr>
</thead>
<tbody class="table-group-divider">
{% for drawing in drawings %}
<tr>
<td>{{ drawing.drawing_number|default_if_none:'' }}</td>
<td>{{ drawing.drawing_name|default_if_none:'' }}</td>
<td>{{ drawing.drawing_type|default_if_none:'' }}</td>
<td>{{ drawing.submission_target_date|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ drawing.end_target_date|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ drawing.wp_date|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ drawing.forecast_date|default_if_none:''|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ drawing.editing_status|default_if_none:'' }}</td>
<td>{{ drawing.approval_status|default_if_none:'' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endif %}
<!-- END: Drawings -->
<br></br>
{% endblock content %}
And yes, the problem_create needs the id supplied to the responsibility_details view.
Best regards
gospat