Create forms that require a foreign key

Hello,

I have the following scenario. I have an overview page with responsibilities. From this page, you can jump into the details of a single responsibility using the view responsibility_details.

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)

The urls.py is as follows.

urlpatterns = [
    path('', views.responsibilities_overview, name='responsibilities-overview'),
    path('responsibility-details/<int:id>/', views.responsibility_details, name='responsibility-details'),
]

So I know the primary key of the responsibility model when calling the view. Any number of problems can now depend on a responsibility and a solution can depend on each of these problems. So I want to create forms in which you can create a problem or a solution to a problem. But how do I pass on the key information? To create a problem, the responsibility_id is required (the one from the call to the view) and when creating a solution, I need the ID of the problem.

Let’s assume that my form for the problem would look something like this.

from django import forms


class ProblemForm(forms.Form):
    # responsibility_id - how do i get it?
    summary = forms.CharField()
    description = forms.CharField()
    # user - should be automatically be filled with the logged in user

models.py.

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}'  

Do I have to solve the whole thing somehow within the responsibility_details view or is there another way?

I would be very happy about a small code snippet as an aid.

Best regards
Patrick

It’s always helpful to keep the fundamentals in mind.

There are three basic ways to pass data from the browser to a view.

The first view prepares the page sent to the browser, for the browser to send to the second view. So the first two options would affect the urls being prepared to access the second view, while the third is going to affect the form itself being rendered.

Hi Ken,

as always, thank you for your support. For me as an absolute beginner in Django, however, it is difficult to understand how I put this into practice now, even despite the documentation. I have now completed my code and show the current version.

forms.py:

from django.forms import ModelForm
from .models import Problem

class ProblemForm(ModelForm):
    class Meta:
        model = Problem
        fields = '__all__'

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, redirect
from .models import Responsibility, BottleneckPart, Drawing, Meeting, Problem
from .filters import ResponsibilityFilter, DrawingFilter
from .forms import ProblemForm


# 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):
    problem_form = ProblemForm()
    if request.method == 'POST':
        problem_form = ProblemForm(request.POST)
        if problem_form.is_valid:
            problem_form.save()
            return redirect('/') # redirect should be to .../responsibilitiy-details/<ID>

    context = {'problem_form': problem_form}
    
    return render(request, 'systemcockpit/problem_form.html', context)


def problem_update(request, id):
    problem = Problem.objects.get(id=id)
    problem_form = ProblemForm(instance=problem)

    if request.method == 'POST':
        problem_form = ProblemForm(request.POST, instance=problem)
        if problem_form.is_valid:
            problem_form.save()
            return redirect('/') # redirect should be to .../responsibilitiy-details/<ID>

    context = {'problem_form': problem_form}
    
    return render(request, 'systemcockpit/problem_form.html', context)

I’m still hanging on the following things:

Relevant part of the template for creating and editing problems.

<a class="btn btn-primary" href="{% url 'problem-create' %}">Problem create</a>
<a class="btn btn-primary" href="{% url 'problem-update' problem.id %}">Problem update</a> 
  1. The ID for responsibility when creating an issue should be automatically populated with the ID of the current website. I don’t want to see a field for this in the form.
  2. After an issue has been created or modified, I want to be redirected to the “original” website (…/responsibility-details/“ID”) …
  3. I would like the logged in user to be automatically filled in when creating or modifying it. The form should therefore not display a field for this either.

I realize that my form probably can’t stay like this (fields = --all–), but since I don’t know how to solve my problem at the moment, I left it that way for now.

Best regards
gospat

I don’t follow what you’re referring to here. I don’t see a field named “website” or anything that I can relate to that.

Then don’t include it in the form.

Again, I need this to be clarified.

Then don’t include it in the form.

You will want to limit the fields to what needs to be sent.

Now, addressing the code you commented:

What ID is it that you are trying to use?

Your url for this path is defined as:

with the name responsibility-details, and so your redirect would be:
redirect('responsibility-details', id=whatever_id)

(This is true in both cases where you’re wanting to redirect to the same view.)

Hi Ken,

I’ll try to outline the process very briefly.

  1. User types the following URL in the browser: http://www.example.com/responsibility-details/1/.
  2. Here he can now create or change new problems and solutions.
  3. If the user creates a new problem, he needs the ID from point 1, i.e. the 1 at the end. This is the ID from the responsibility model.
  4. If point 3 has been completed successfully, the user should be led back to the URL from point 1.

So my problem is that I don’t know how I have to pass the ID from point 1 to the form or how I have to specifically use it there.

Best regards
gospat

For the view (responsibility_details) for that url, I see a number of queries, but I do not see any forms being rendered.

How are they entering data on that page?

Hi Ken,

actually my plan was that no form would be rendered in this view. This view should initially only show the details of this specific object.

I simply wanted to integrate 2 buttons in the responsibilties_overview.html template. Once “Create problem” and once “Create solution”. When you click on the first button, a view called problem_create should be used and when you click on the second button, a view called solution_create should be used. The respective form should then be used in these two views. In these forms I then need the IDs, the ID of the responsibility model for the problem and the ID of the problem for the solution.

Best regards
Patrick

Ok, this is where we need to get more granular - trying to talk about two different views with potentially different requirements can confuse the issue.

So lets focus on the first view, “Create Problem”

  • Does it need the id supplied to the responsibility_details view?
    If so:
    • What is the name of that view?
    • What is its url definition?
    • How are you creating that link in your html?

If not, how is it an issue here?

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

You need to do the same thing with your problem-create url as you do with your responsibility-details.

  • Add the id parameter to the url definition
  • Accept the parameter in the function call
  • Render the problem-create url in the responsibility-details view with the id.

So I have to put responsibility.id at the end of the link to the problem-create view in the template, right?

Just id. That’s the name of the variable that is being passed in to the responsibility-details view.

Ok, and how can I use this ID in my form? I saw something like initial for a Field in the view. Is this the correct way?

Why do you want to use this in the form? (Or perhaps to phrase this a bit differently, What do you want to do with it?)

Your view has it available.

To create a new Problem I need the responsibility id. I thought I have to pass it somehow to the Form.

Nope.

See the docs for The save method. What you’re trying to do with the responsibility id is functionally similar to what the example in the docs is doing with “some field”.

Ok, I’ll make the changes step by step, as I understand it.

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/<int:id>/', views.problem_create, name='problem-create'), # added /<int:id>
    path('problem-update/<int:id>/', views.problem_update, name='problem-update'),
]

responsibiliy_details.html:

<a href="{% url 'problem-create' responsibility.id %}">Problem create</a> # added responsibility.id in the a element

views.py:

def problem_create(request, id): # added the id to the function
    
    # ProblemForm

    context = {}
    
    return render(request, 'systemcockpit/problem_form.html', context)

Is all this correct so far? I don’t know exactly what you mean by “Render the problem-create url in the responsibility-details view with the id”

There’s no need to access this from the object, but technically, it’s not “wrong”.

That’s exactly what you’ve done above. You’re rendering the problem-create url, with a parameter, by using the {% url %} tag.

And your problem_create view is good so far.

Ok, I changed the one with the id.

I saw the other variant in a tutorial and therefore thought it was right. This is my very first Django project, I’m sorry if I’m sometimes a bit on the tube. Programming is also still quite new to me in general.

Ok, short feedback.

If I turn responsibility.id only id, the following error message appears:

NoReverseMatch at /responsibility-details/10/
Reverse for 'problem-create' with arguments '('',)' not found. 1 pattern(s) tried: ['problem\\-create/(?P<id>[0-9]+)/\\Z']

The original variant works.

views.py:

def problem_create(request, id):
    if request.method == 'POST':
        problem_form = ProblemForm(request.POST)
        if problem_form.is_valid():
            problem_form.save()

            return HttpResponseRedirect('/responsibility-details/') # actually it should redirect to the responsibility with the id from the view
    else:
        problem_form = ProblemForm()

    context = {'problem_form': problem_form}
    
    return render(request, 'systemcockpit/problem_form.html', context)

I’m sorry, but despite the documentation I don’t know what to do with the ID now? Can you possibly show me that with a line of code? That would be great. I also don’t know how to specify the URL including ID in the redirect.