Why is bootstrap able to load the backdrop for one modal but not the other
so here's my issue im building a django project based off of tutorials ect and I found for user feedback modals to be a good idea. I didn't want to create a lot of different code pieces for modals so i decided to opt for a generic modal that i can use for all my cases.
<div class="modal fade" id="{{ modal_id }}" tabindex="-1" role="dialog" aria-labelledby="{{ modal_id }}Label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="{{ modal_id }}Label">{{ title }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<!-- Dynamic message -->
<p id="modalMessage">{{ message }}</p>
<!-- Conditional content based on context_type -->
{% if context_type == "account_deletion" %}
<form method="POST" action="{{ action_url }}">
{% csrf_token %}
<div class="form-group">
<label for="password" style="margin-bottom:1rem;">Enter Your Password to Confirm:</label>
<input type="password" id="password" name="password" class="form-control" required style="margin-bottom: 1rem;">
</div>
<button type="submit" class="btn btn-danger">Delete Account</button>
</form>
{% elif context_type == "item_deletion" %}
<p>Are you sure you want to delete this item?</p>
{% endif %}
</div>
<div class="modal-footer">
{% if context_type == "item_deletion" %}
<form method="POST" action="{{ action_url }}">
{% csrf_token %}
<button type="submit" class="btn {{ submit_class }}">{{ submit_label }}</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
</form>
{% endif %}
</div>
</div>
</div>
</div>
in this project there will only be two cases, either the user wants to do something serious like account deletion, then they would need to enter their password to confirm.
or just to confirm deletion of a recommendation or comment ect.
this is where the problem lies. For some reason the modal works just fine when i want to delete an account, but if i want to delete a recommendation from the user profile, it doesn't open the modal and throws this error at me:
[![enter image description here][1]][1]
I figured it was the modal formatting but that's not the case as again works fine with my account deletion, and after that i assumed it may be way im accessing it but again not sure. I also tried moving the modal include to the bottom of the loop and outside the loop entirely.
The only reasonable thing i can think it is, is that it's either trying to load a non existent recommendation or the way i have setup the button is wrong? but i don't know.
Here's extra code anyway for reference.
{% extends "base.html" %}
{% load static %}
{% block content %}
<h2>{{ profile.user.username }}'s Profile</h2>
<p>Bio: {{ profile.bio }}</p>
<p>Location: {{ profile.location }}</p>
{% if profile.avatar %}
<img src="{{ profile.avatar.url }}"
alt="{{ profile.user.username }}'s avatar"
class="profile-avatar">
{% else %}
<img src="{% static 'images/default_avatar.png' %}"
alt="Default avatar"
class="profile-avatar">
{% endif %}
{% if user.is_authenticated %}
{% if user == profile.user %}
<!-- Show the edit profile button only if the logged-in user is the profile owner -->
<a href="{% url 'edit_profile' username=request.user.username %}"
class="btn btn-primary">
Edit Profile
</a>
<a href="{% url 'delete_account' username=request.user.username %}" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteAccountModal">
Delete Account
</a>
{% endif %}
{% endif %}
<!-- Display Recommendations -->
<h3>Recommendations</h3>
{% for recommendation in recommendations %}
<div class="recommendation">
<p>{{ recommendation.content }}</p>
{% if user == profile.user %}
<a href="{% url 'edit_recommendation' recommendation_id=recommendation.id %}" class="btn btn-primary">Edit</a>
<button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteRecommendationModal{{ recommendation.id }}">
Delete
</button>
<!-- Delete Recommendation Confirmation Modal -->
{% include "modal/modal.html" with modal_id="deleteRecommendationModal"|add:recommendation.id title="Confirm Recommendation Deletion" message="Are you sure you want to delete this recommendation?" context_type="item_deletion" action_url=recommendation.delete_url submit_class="btn-danger" submit_label="Delete Recommendation" %}
{% endif %}
</div>
{% endfor %}
<!-- Account Deletion Confirmation Modal -->
{% include "modal/modal.html" with modal_id="deleteAccountModal" title="Confirm Account Deletion" message="This action is irreversible. Please confirm." context_type="account_deletion" action_url=delete_account_url submit_class="btn-danger" submit_label="Delete Account" %}
{% endblock %}
(my profile.html code)
def profile(request, username):
"""
Profile view to display user profile along with their recommendations.
Args:
request (HttpRequest): The request object to handle the request.
username (str): The username of the user whose profile is being viewed.
Returns:
HttpResponse: Renders the profile page with the user's profile and recommendations.
"""
user = get_object_or_404(User.objects.select_related('profile'), username=username)
recommendations = Recommendation.objects.filter(user=user)
delete_account_url = reverse("delete_account", kwargs={"username": username})
return render(request, "profiles/profile.html", {
"profile": user.profile,
"recommendations": recommendations,
"can_edit": request.user == user,
"delete_account_url": delete_account_url,
})
(my profile view)
def delete_recommendation(request, recommendation_id):
"""
Handles the deletion of an existing recommendation.
Args:
request: The HTTP request object containing user data.
recommendation_id (int): The ID of the recommendation to be deleted.
Returns:
Redirects to the user's profile page after the recommendation is deleted.
Description:
This view allows the logged-in user to delete their own recommendation.
If the user is not the owner of the recommendation, they are redirected
to their profile page.
"""
recommendation = get_object_or_404(models.Recommendation, id=recommendation_id)
#defensive programming stop user from navigating via url to delete others recommendation
if recommendation.user != request.user:
return render(request, "error/403.html", status=403)
recommendation.delete()
messages.success(request, "Recommendation deleted successfully!")
return redirect('profile', username=request.user.username)
delete recommendation view
class Recommendation(models.Model):
"""Recommendation model
Args:
models (django model class): class from djangos model framework
Description:
recommendation model for the database, once created here get's migrated
to the database and is used for allowing users to see active recommendations
made
"""
def __str__(self):
"""String func
Returns:
formatted string for admin viewing
"""
return f"{self.title} | Recommended by {self.user}"
#title of the recommendation
title = models.CharField(max_length=100, unique=True)
# user, our fk linking back to the user who created it
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="recommendations",
)
# optional description field for the recommendation
description = models.TextField(max_length=200, blank=True, null=True)
# we add lat/long cords for rec to put on map (invisible to user)
latitude = models.FloatField(blank=True, null=True)
longitude = models.FloatField(blank=True, null=True)
# address of place in question
address = models.CharField(max_length=255, unique=True)
# Many-to-many field for categories
categories = models.ManyToManyField(
Category,
related_name="recommendations",
blank=True,
)
def average_score(self):
"""
Average Score Func
Args:
self: (num): number to average
Description:
Method to calculate the votes, the votes are added by users and calculated here
when the object (recommendation) is displayed, the vote is tallied and then shown
"""
votes = self.votes.all()
if votes.count() == 0:
# No votes, return 0 as default
return 0
total_score = sum(vote.vote for vote in votes)
# Return the average score, rounded to 1 decimal place
return round(total_score / votes.count(), 1)
def delete_url(self):
return reverse("delete_recommendation", args=[self.id])
urlpatterns = [
path("recommendations/", recommendations, name="recommendations"),
path("add_recommendation/", add_recommendation, name="add_recommendation"),
path("edit_recommendation/<int:recommendation_id>/", edit_recommendation, name="edit_recommendation"),
path("delete_recommendation/<int:recommendation_id>/", delete_recommendation, name="delete_recommendation"),
]
finally recommendation model (cos the tutorial had me add a backref) and recommendation views
any help would be appreciated [1]: https://i.sstatic.net/pT9bLGfg.png
EDIT 1:
So a quick edit i broke this button in the profile.html
From:
<button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteRecommendationModal{{ recommendation.id }}">
Delete
</button>
<!-- Delete Recommendation Confirmation Modal -->
To:
<button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteRecommendationModal{{ recommendation.id }}">
<!-- Delete Recommendation Confirmation Modal -->
the button still doesn't work but it shows the modal text (and buttons) and does delete when it works so i think the error is in here