Django Form(Formset) is not working - id is missing?

29 views Asked by At

My template form does not save the objects. here is my view:

class FeatureDeliveryEditView(
    LoginRequiredMixin, PermissionRequiredMixin, SingleObjectMixin, FormView
):
    permission_required = "auth.can_access_supervising_sections"
    model = FeatureFilm
    template_name = "project/project_update/feature/update_featurefilm_delivery.html"

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super().get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super().post(request, *args, **kwargs)

    def get_form(self, form_class=None):
        return FeatureDeliveryFormSet(**self.get_form_kwargs(), instance=self.object)

    def form_valid(self, form):
        form.save()
        messages.success(self.request, "Delivery erfolgreich gespeichert")
        return HttpResponseRedirect(self.get_success_url())

    def form_invalid(self, form):
        messages.error(
            self.request, f"Delivery nicht gespeichert: {form.errors}"
        )
        return super().form_invalid(form)

    def get_success_url(self):
        return (
            reverse("feature-detail-deliveries-half", kwargs={"pk": self.object.pk})
            + "#content-start-under-cards"
        )

    def handle_no_permission(self):
        return redirect("access-denied")

and here is my form and formset:

    class FeatureDeliveryForm(ModelForm):
    class Meta:
        model = Delivery
        exclude = (
            "feature_id",
            "tv_movie_id",
            "tv_serie_block_id",
            "restoration_id",
            "source_material",
            "scan_info",
            "usage_version",
            "orderer_id",
            "receiver_1_id",
            "receiver_2_id",
            "receiver_3_id",
        )
        widgets = {
            'trade_mark_brand': forms.Textarea(attrs={'rows': 1}),
            'audio_channel_assignment': forms.Textarea(attrs={'rows': 1}),
            'notes': forms.Textarea(attrs={'rows': 1}),
            # ... Andere Widgets hier
        }


FeatureDeliveryFormSet = inlineformset_factory(
    FeatureFilm,
    Delivery,
    form=FeatureDeliveryForm,
    can_delete=True,
)

if i used this template the form will be saved and all is working:

{% extends "_base.html" %}
{% load crispy_forms_tags %}

{% block content %}

<div class="container">
    <div class="row py-5">
        <h3 class="text-center">{{ object }} - Delivery hinzufügen/editieren</h3>
    </div>
    <div class="row">

          <form method="post" enctype="multipart/form-data">

             {% for hidden_field in form.hidden_fields %}
                {{ hidden_field.errors }}
                {{ hidden_field }}
            {% endfor %}

                {% csrf_token %}

         {{ form.management_form }}
         {{ form.non_form_errors }}

         {% for delivery_form in form.forms %}
            <hr>

                {% if delivery_form.instance.id %}

                    {% if form.forms|length > 1 %}
                        <h5 class="text-warning">Delivery hinzufügen<br><br></h5>
                    {% else %}
                        Delivery hinzufügen<br><br>
                    {% endif %}
                {% endif %}

               <table>

                {{ delivery_form.as_table}}
               </table>



            {% endfor %}
            <hr>
            <p>
                <button type="submit" value="Update Collection" class="btn btn-primary btn-sm">Speichern</button>
                <a href="{% url 'feature-detail-genre-content' pk=object.pk %}#content-start-under-cards" class="btn btn-secondary btn-sm">Zurück</a>
             </p>

         </form>

    </div>
</div>


{% endblock %}

But this functioning template unfortunately does not represent the form in the way I envision. Each object and its fields are displayed one below the other. However, I want the fields of an object to be displayed side by side, and each additional object to receive a new line. Therefore, I have built the following template. The visual representation is exactly as I imagine it, but unfortunately, the form functionality, more precisely, the saving, no longer works. The form itself gives me an error for each object, stating that the 'id' is missing. Unfortunately, I cannot find the solution.

    {% extends "_base.html" %}
{% load crispy_forms_tags %}

{% block content %}

<div class="container">
    <div class="row py-5">
        <h3 class="text-center">{{ object }} - Delivery hinzufügen/editieren</h3>
    </div>
    <div class="row">


        <form method="post" enctype="multipart/form-data">
            {% csrf_token %}
{#            {{ form.management_form }}#}
{#            {{ form.non_form_errors }}#}

        <table class="table table-dark table-bordered">
                    <thead>
                        <tr>
                            <th>Action</th>
                            <th>Del. Nummer</th>
                            <th>Besteller</th>
                            <th>Empfänger 1</th>
                            <th>Content</th>
                            <th>Produkt</th>
                           
                        </tr>
                    </thead>
                    <tbody>

            {% for delivery_form in form.forms %}

                        <tr>
                        <td>
                        {% if delivery_form.instance.id %}
                            {% if form.forms|length > 1 %}
                                <p class="text-warning">ändern</p>
                            {% endif %}
                            {% else %}
                            <p class="text-success">hinzufügen</p>
                        {% endif %}
                        </td>
                            <td>{{ delivery_form.delivery_number }}</td>
                            <td>{{ delivery_form.orderer_id }}</td>
                            <td>{{ delivery_form.receiver_1_id }}</td>
                            <td>{{ delivery_form.content }}</td>
                            <td>{{ delivery_form.product }}</td>
                    
                        </tr>

            {% endfor %}
                 </tbody>
                </table>

            <hr>
            <p>
                <button type="submit" value="Update Collection" class="btn btn-primary btn-sm">Speichern</button>
                <a href="{% url 'feature-detail-genre-content' pk=object.pk %}#content-start-under-cards" class="btn btn-secondary btn-sm">Zurück</a>
            </p>

        </form>


    </div>
</div>


{% endblock %}

Kann jemand helfen ?

1

There are 1 answers

0
gomez_ On

"I now know what was missing and would like to share it with you. I had forgotten that the ID of the object also needs to be included in the form. So, I added additional targets to my template, and now the form saving functionality is working."

<form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {{ form.management_form }}
        {{ form.non_form_errors }}

    <table class="table table-dark table-bordered">
                <thead>
                    <tr>
                        <th>Action</th>
                        <th>Del. Nummer</th>
                        <th>Besteller</th>
                        <th>Empfänger 1</th>
                        <th>Content</th>
                        <th>Produkt</th>
                        
                        <th>DELETE</th>
                    </tr>
                </thead>
                <tbody>

        {% for delivery_form in form.forms %}

                    <tr>
                    <td>
                    {% if delivery_form.instance.id %}
                        {% if form.forms|length > 1 %}
                            <p class="text-warning">ändern</p>
                        {% endif %}
                        {% else %}
                        <p class="text-success">hinzufügen</p>
                    {% endif %}
                    </td>
                        <td>{{ delivery_form.delivery_number }}</td>
                        <td>{{ delivery_form.orderer_id }}</td>
                        <td>{{ delivery_form.receiver_1_id }}</td>
                        <td>{{ delivery_form.content }}</td>
                        <td>{{ delivery_form.product }}</td>
                  
                         <td>
                            {{ delivery_form.DELETE }}
                            {{ delivery_form.id }}
                            {{ delivery_form.feature_id }}
                        </td>
                        <!-- Füge hier die übrigen Feldwerte hinzu -->
                    </tr>

        {% endfor %}
             </tbody>
            </table>