Problem Description:
I am developing a Django application and I am encountering a RuntimeError
when trying to submit a form. The error states: “You called this URL via POST, but the URL doesn’t end in a slash and you have APPEND_SLASH set. Django can’t redirect to the slash URL while maintaining POST data.”
Technical Details:
- asgiref 3.7.2 ASGI specs, helper code, and adapters
- beautifulsoup4 4.12.2 Screen-scraping library
- brotli 1.0.9 Python bindings for the Brotli compression library
- dj-database-url 2.0.0 Use Database URLs in your Django Application.
- django 4.1.3 A high-level Python web framework that encourages rapid development and clean, pragmatic design.
- django-bootstrap-v5 1.0.11 Bootstrap 5 support for Django projects
- django-ckeditor 6.5.1 Django admin CKEditor integration.
- django-js-asset 2.0.0 script tag with additional attributes for django.forms.Media
- djangorestframework 3.14.0 Web APIs for Django, made easy.
- et-xmlfile 1.1.0 An implementation of lxml.xmlfile for the standard library
- gunicorn 20.1.0 WSGI HTTP Server for UNIX
- numpy 1.25.2 Fundamental package for array computing in Python
- openpyxl 3.1.2 A Python library to read/write Excel 2010 xlsx/xlsm files
- pandas 2.1.0 Powerful data structures for data analysis, time series, and statistics
- pillow 9.3.0 Python Imaging Library (Fork)
- psycopg2-binary 2.9.6 psycopg2 - Python-PostgreSQL Database Adapter
- python-dateutil 2.8.2 Extensions to the standard Python datetime module
- pytz 2023.3 World timezone definitions, modern and historical
- six 1.16.0 Python 2 and 3 compatibility utilities
- soupsieve 2.4.1 A modern CSS selector implementation for Beautiful Soup.
- sqlparse 0.4.4 A non-validating SQL parser.
- typing-extensions 4.6.3 Backported and Experimental Type Hints for Python 3.7+
- tzdata 2023.3 Provider of IANA time zone data
- whitenoise 6.5.0 Radically simplified static file serving for WSGI applications
Detailed Description:
The error occurs when I try to submit a messaging form in my application. This form is meant to send messages, either in the general context of the application or linked to a specific project (identified by projet_id
).
Relevant Code:
Vue messagerie
@login_required(login_url='/user/')
def messagerie(request, projet_id=None):
projet = None
context = {}
if projet_id:
projet = get_object_or_404(Projet, pk=projet_id)
context['projet_id'] = projet_id
if request.method == 'POST':
print('message POST')
form = MessageForm(request.POST, request.FILES, user=request.user)
if form.is_valid():
objet = form.cleaned_data["objet"]
messages = form.cleaned_data["messages"]
recepteurs = form.cleaned_data["recepteurs"]
msg = Message(
objet=objet,
messages=messages,
emetteur=request.user,
date_envoie=datetime.datetime.now(datetime.timezone.utc),
status_envoie=True,
projet = projet
)
msg.save()
for user in recepteurs:
msg.recepteurs.add(user)
#send_notification_email(user, objet)
#form = MessageForm(user=request.user)
form = MessageForm(user=request.user, projet=projet)
else:
print('message GET')
#form = MessageForm(user=request.user)
form = MessageForm(user=request.user, projet=projet)
#context = {'form': form}
context['form'] = form
template = loader.get_template('message.html')
return HttpResponse(template.render(context, request))
** forms **
from django import forms
from .models import User
from ckeditor.widgets import CKEditorWidget
class MessageForm(forms.Form):
objet = forms.CharField(max_length=200)
messages = forms.CharField(required=False, widget=CKEditorWidget())
recepteurs = forms.ModelMultipleChoiceField(
queryset=User.objects.all(),
required=False,
)
documents = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}), required=False)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
projet = kwargs.pop('projet', None)
super(MessageForm, self).__init__(*args, **kwargs)
if user:
self.fields['recepteurs'].queryset = User.objects.exclude(id=user.id)
if projet:
# Si un projet est spécifié, filtrez les utilisateurs en fonction de ce projet
#self.fields['recepteurs'].queryset = projet.get_all_users().exclude(id=user.id) if user else projet.get_all_users()
# Convertir les utilisateurs du projet en liste d'identifiants
user_ids = [u.id for u in projet.get_all_users()]
# Filtrer le queryset des récepteurs pour inclure uniquement les utilisateurs du projet
self.fields['recepteurs'].queryset = User.objects.filter(id__in=user_ids)
urls.py (extraits) :
from django.urls import path
from . import views
app_name = 'mailmanagement'
urlpatterns = [
# Ajouter 'projet_id' comme paramètre facultatif dans les URL
path('<int:projet_id>/message/', views.messagerie, name="messagerie"),
path('entrant/<int:projet_id>/', views.courier_entrant, name="entrant"),
path('envoye/<int:projet_id>/', views.courier_envoye, name='courier_envoye'),
path('projet/<int:projet_id>/', views.boitemessagerie, name="inbox_projet"),
# Ajouter des URL sans 'projet_id' pour les cas où le projet n'est pas spécifié
path('', views.boitemessagerie, name="inbox"),
path('message/<int:message_id>/', views.detail_message, name='detail_message'),
path('reply/<int:message_id>/', views.reply_to_message, name='reply_to_message'),
path('message/', views.messagerie, name="messagerie_general"),
path('entrant/', views.courier_entrant, name="entrant_general"),
path('envoye/', views.courier_envoye, name='courier_envoye_general'),
]
template
{% extends "home.html" %}
{% block entete_messagerie %}
<div class="row container-fluid border border-warning">
<div class="d-flex p-2 bd-highlight col-sm border border-success">
{% load static %}
{% if projet_id %}
<!-- Lien vers la messagerie du projet -->
<a href="{% url 'mailmanagement:messagerie' projet_id %}">
<img src="{% static 'images/write_email.png' %}" alt="email" title="email" />
</a>
{% else %}
<!-- Lien vers la messagerie générale -->
<a href="{% url 'mailmanagement:messagerie_general' %}">
<img src="{% static 'images/write_email.png' %}" alt="email" title="email" />
</a>
{% endif %}
<form method="POST" action='{% if projet_id %} {% url "mailmanagement:messagerie" projet_id %}/ {% else %} {% url "mailmanagement:messagerie_general" %}/ {% endif %}' role="search" style="width: 15em; margin: 0.3em 2em;">
{% csrf_token %}
<div class="input-group">
<input type="text" class="form-control" placeholder="Search">
<div class="input-group-btn">
<button type="submit" class="btn btn-default">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
</div>
</form>
</div>
</div>
{% endblock %}
{% block menu %}
{{ user.email }}
<div class="list-group">
{% load static %}
{% if projet_id %}
<a href="{% url 'mailmanagement:entrant' projet_id %}" class="list-group-item list-group-item-action">
<img src="{% static 'images/courrier-entrant.png' %}" alt="email" title="email" /> Courrier entrant du Projet
</a>
<a href="#" class="list-group-item list-group-item-action"> <img src="{% static 'images/brouillon.png' %}" alt="email" title="email" /> Brouillons du Projet</a>
<a href="{% url 'mailmanagement:courier_envoye' projet_id %}" class="list-group-item list-group-item-action">
<img src="{% static 'images/envoye.png' %}" alt="email" title="email" />Courrier Envoyés du Projet</a>
<a href="#" class="list-group-item list-group-item-action"><img src="{% static 'images/corbeille.png' %}" alt="email" title="email" />Corbeille du Projet</a>
<!-- Ajouter d'autres liens spécifiques au projet ici -->
{% else %}
<a href="{% url 'mailmanagement:entrant_general' %}" class="list-group-item list-group-item-action">
<img src="{% static 'images/courrier-entrant.png' %}" alt="email" title="email" /> Courier entrant
</a>
<a href="#" class="list-group-item list-group-item-action">
<img src="{% static 'images/brouillon.png' %}" alt="email" title="email" />
Brouillons
</a>
<a href="{% url 'mailmanagement:courier_envoye_general' %}" class="list-group-item list-group-item-action">
<img src="{% static 'images/envoye.png' %}" alt="email" title="email" />
Envoyés
</a>
<a href="#" class="list-group-item list-group-item-action">
<img src="{% static 'images/corbeille.png' %}" alt="email" title="email" />
Corbeille
</a>
{% endif %}
<a href="/" class="list-group-item list-group-item-action">
<img src="{% static 'images/menu.png' %}" alt="email" title="menu " />
Return to Menu
</a>
</div>
{% endblock %}
Encountered Issues:
- When submitting the form, I receive the aforementioned
RuntimeError
. - I have checked that all URLs in
urls.py
and in the template end with a slash (“/”). - I tried adding a slash at the end of the form action in the template, but this did not resolve the issue.