Django Form not rendering/loading in BS modal

Question:

i am trying to get a Form into a BS modal but the modal is always empty.
Searched very much for a solution but nothing worked yet and im helpless.
As im quite new to Python and Django i tried to set up a small Event page for updating/adding/deleting Events and Venues for Events.

my views.py

from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect
from .models import Event, Venue
from .forms import VenueForm, EventForm
from django.db.models.functions import Lower

def add_event(request):
    submitted = False
    if request.method == "POST":
        form = EventForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/add_event?submitted=True')
    else:
        form = EventForm
        if 'submitted' in request.GET:
            submitted = True

    return render(request, 'events/add_event.html', {'form': form, 'submitted': submitted})

def list_venues(request):
    venue_list = Venue.objects.all().order_by(Lower('name'))
    return render(request, 'events/venues.html', {
        "venue_list": venue_list,
    })


def add_venue(request):
    submitted = False
    if request.method == "POST":
        form = VenueForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('/')
    else:
        form = VenueForm
        if 'submitted' in request.GET:
            submitted = True
    return render(request, 'events/add_venue.html', {'form': form, 'submitted': submitted})

def all_events(request):
    event_list = Event.objects.all().order_by(Lower('name'))
    return render(request, 'events/event_list.html', {
        "event_list": event_list,
    })

urls.py

from django.urls import path
from . import views

urlpatterns = [
    # in
    path('events/', views.all_events, name="list-events"),
    path('add_venue', views.add_venue, name="add-venue"),
    path('list_venues', views.list_venues, name="list-venues"),
    path('add_event', views.add_event, name="add-event"),
]

Models.py

from django.db import models
from django.contrib.auth.models import User


class Venue(models.Model):
    name = models.CharField('Venue Name', max_length=120)
    address = models.CharField(max_length=300)
    zip_code = models.CharField('ZIP Code', max_length=15)

    def __str__(self):
        return self.name


class Event(models.Model):
    name = models.CharField('Event Name', max_length=120)
    event_date = models.DateTimeField('Event Date')
    venue = models.ForeignKey(
        Venue, blank=True, null=True, on_delete=models.CASCADE)
    description = models.TextField(blank=True)

    def __str__(self):
        return self.name

at first i have created simple html files to be opened and passed the form in like

{% csrf_token %}
{{ form.as_p }}

which worked perfectly. (Done this with both forms add Event and add Venue)
Now i tried to change the add_Venue From, to get it into a BS Modal but it is keeping empty.

My add_event.html is loocking like this:

{% extends 'events/base.html' %}
{% block content %}
    <h1>Add Event..</h1>
    <br/><br />    
    <form action="" method=POST>
        {% csrf_token %}        
        {{ form.as_p }}
        <input type="submit" value="Submit" class="btn btn-secondary">
    </form>
    <br /><br />
{% endblock %}

And the add_Venue.html with the Modal:

<div class="modal fade" id="addVenueModal" tabindex="-1" role="dialog" aria-labelledby="addVenueModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="addVenueModalLabel">Add Venue2</h5>
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;
                </button>
            </div>
            <div class="modal-body">
                <div class="container txt-box">
                    <form action="" role="form" method="post">
                        {% csrf_token %}
                        {{ form.as_p }}                    
                    <input type="submit" value="Submit" class="btn btn-secondary">                    
                </div>
        </div>
    </div>
</div>

I wanted to call this from every page i have thats why i added the button into the navbar:

<li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
        Events
    </a>
    <ul class="dropdown-menu" style="right:auto; left: auto; text-align:left;">
        <li><a class="dropdown-item" href="{% url 'list-events' %}">list Events</a></li>
        <li><a class="dropdown-item" href="{% url 'add-event' %}">Add Event</a></li>
    </ul>
</li>
<li class="nav-item dropdown" >
    <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
        Venues
    </a>
    <ul class="dropdown-menu" style="right:auto; left: auto; text-align:left;">
        <li><a class="dropdown-item" href="{% url 'list-venues' %}">list Venues</a></li>
        <li><a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#addVenueModal">Add Venue</a></li>
    </ul>
</li>

(this is just the snipped from the navbar)

i also included the add_venue.html into my base.html

<!doctype html>
<html lang="en">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.rtl.min.css" integrity="sha384-WJUUqfoMmnfkBLne5uxXj+na/c7sesSJ32gI7GfCk4zO4GthUKhSEGyvQ839BC51" crossorigin="anonymous">
    <title>Hello World</title>
</head>

<body>
    {% include 'events/navbar.html' %}

    <br/>
    <div class="container">
        {% if messages %}
            {% for message in messages %}
                
                <div class="alert alert-warning alert-dismissible fade show" role="alert">
                    <strong>{{ message }}</strong>
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                </div>
            {% endfor %}
        {% endif %}

        {% block content %}
        {% endblock content%}
        {% include 'events/add_venue.html' %}
    </div>
    
    <!-- Optional JavaScript; choose one of the two! -->

    <!-- Option 1: Bootstrap Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
    <!-- Option 2: Separate Popper and Bootstrap JS -->
    
    <!-- script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-mQ93GR66B00ZXjt0YO5KlohRA5SY2XofN4zfuZxLkoj1gXtW8ANNCe9d5Y3eG5eD" crossorigin="anonymous"></script>
    -->
</body>
</html>

I really tried everything i found but nothing worked so far.
One thing i figured out was, calling the add_event.html and then calling the modal the add_event form is beeing loaded inside the modal.
What am i missing?

Asked By: s0Nic

||

Answers:

Ok i got this finally myself. Just wanted to post the solution, if anyone else have the same problem. If i am explaining something wrong please correct me.

Above you can see that my djangoforms are already built. (forms.py)
Im using a navbar.html for navigation and included this into my base.html.

What i have done:

Changed the add_venue view in
views.py:

def add_venue(request):
    if request.method == 'POST':
        form = VenueForm(request.POST)
        if form.is_valid():
            form.save()
            return JsonResponse({'success': True})
        else:
            return JsonResponse({'success': False, 'errors': form.errors})
    else:
        form = VenueForm()
        return JsonResponse({'html': render_to_string('events/add_venue_form.html', {'form': form}, request=request)})

Then i changed my add_venue.html:

<!-- Modal -->
<head>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>

<script>
    $(document).ready(function () {
        console.log("ready");
        $('#venueModal').on('show.bs.modal', function () {
            console.log("modal show");
            $.ajax({
                type: 'GET',
                url: "{% url 'add-venue' %}",
                dataType: 'json',
                success: function (data) {
                    console.log("ajax success");
                    $('#venueModal .modal-body').html(data.html);
                },
                error: function (xhr, status, error) {
                    console.log("ajax error");
                    alert('An error occurred while loading the form.');
                }
            });
        });
    });
</script>

<div class="modal fade" id="venueModal" tabindex="-1" aria-labelledby="venueModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="venueModalLabel">Venue hinzufügen</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <!-- Hier wird das Formular eingesetzt -->
                <form method="POST">
                    {% csrf_token %}
                    {{ form.as_p }}
                    <button type="submit" class="btn btn-primary">Speichern</button>
                </form>
            </div>
        </div>
    </div>
</div>

but this is not enough because form is not rendering.
created a add_venue_from.html

<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit" class="btn btn-primary">Speichern</button>
</form>

(see the view response)
making sure urls.py in correct:

urlpatterns = [
    # in
    ...
    path('add_venue', views.add_venue, name="add-venue"),
    ...
]

make sure JQuery and JS is in base.html

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
{% load static %}
<!-- Bootstrap JavaScript -->
<script src="{% static 'js/bootstrap5.modal.forms.js' %}"></script>

and include the add_venue.html also in base.html

{% include 'events/add_venue.html' %}

this is just about rendering the form! Not done the submit function.
Will add this to the answer when i have it.

EDIT:

to save the form:
add_venue_form.html:

<form method="POST" id="venueForm" action="{% url 'add-venue' %}">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit" class="btn btn-primary">Speichern</button>
</form>

now the form will be saved.

Answered By: s0Nic
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.