I am new to Django and am having trouble with the generic UpdateView.
Following the tutorial, this should be the simplest thing but submitting the form yields this error: DisallowedRedirect. I’m sure it is a very simple thing missing but reading the documentation over and over I can’t find it. Please help.
The generic ListView works fine, with a link to the correct URL for UpdateView and displaying the expected form. Data entered into the form does actually get saved correctly prior to the error. The offending target URL that generates the error looks just fine.
Here is the error generated by the server:
Environment:
Request Method: POST
Request URL: http://localhost:8000/glazeman/element/4
Django Version: 3.1
Python Version: 3.8.5
Installed Applications:
['glazes.apps.GlazesConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "C:\Users\Ken\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\Ken\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Ken\AppData\Local\Programs\Python\Python38\lib\site-packages\django\views\generic\base.py", line 73, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\Ken\AppData\Local\Programs\Python\Python38\lib\site-packages\django\views\generic\base.py", line 101, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\Ken\AppData\Local\Programs\Python\Python38\lib\site-packages\django\views\generic\edit.py", line 194, in post
return super().post(request, *args, **kwargs)
File "C:\Users\Ken\AppData\Local\Programs\Python\Python38\lib\site-packages\django\views\generic\edit.py", line 142, in post
return self.form_valid(form)
File "C:\Users\Ken\AppData\Local\Programs\Python\Python38\lib\site-packages\django\views\generic\edit.py", line 126, in form_valid
return super().form_valid(form)
File "C:\Users\Ken\AppData\Local\Programs\Python\Python38\lib\site-packages\django\views\generic\edit.py", line 57, in form_valid
return HttpResponseRedirect(self.get_success_url())
File "C:\Users\Ken\AppData\Local\Programs\Python\Python38\lib\site-packages\django\http\response.py", line 468, in __init__
raise DisallowedRedirect("Unsafe redirect to URL with protocol '%s'" % parsed.scheme)
Exception Type: DisallowedRedirect at /glazeman/element/4
Exception Value: Unsafe redirect to URL with protocol 'glazes'
Here are the urls, models, views and template files:
urls.py
from django.urls import path
from . import views
app_name = 'glazes'
urlpatterns = [
path('', views.index, name='index'),
path('elements', views.ElementsView.as_view(), name='elements index'),
path('element/<int:pk>', views.Element_detailView.as_view(), name='element detail'),
]
models.py
from django.db import models
class Element(models.Model):
name = models.CharField(max_length=200, unique=True)
toxic = models.BooleanField(default = False)
quantity = models.DecimalField(max_digits=20, decimal_places=3, blank = True, null = True) # inventory in grams
price = models.DecimalField(max_digits=6, decimal_places=2, blank = True, null = True) # stored as $/gram
note = models.TextField(blank = True)
def __str__(self):
return self.name
class Meta:
ordering = ['name']
views.py
from django.http import HttpResponse
from django.views import generic
from .models import Element
def index(request):
breakpoint()
return HttpResponse("Hello, world. You're at the index.")
class ElementsView(generic.ListView):
model = Element
template_name = 'glazes/elements.html'
context_object_name = 'elements_list'
def get_queryset(self):
return Element.objects.order_by('name')
class Element_detailView(generic.UpdateView):
model = Element
fields = ['toxic', 'note', 'quantity']
template_name = 'glazes/element_detail.html'
success_url = 'glazes:element detail'
template\element_detail.html
<h1>{{ element }}</h1>
<br>
<form method = "post">
{% csrf_token %}
{{ form.as_p }}
<br>
<input type="submit" value="Save">
</form>
<br>
<a href="{% url 'glazes:element detail' element.id %}">Should do a get</a>
<br>
<a href="{% url 'glazes:elements index' %}">Back to Elements index</a>
templates/elements.html
{% if elements_list %}
<ul>
{% for element in elements_list %}
<li><a href="{%url 'glazes:element detail' element.id %}">{{ element.name }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No elements are available.</p>
{% endif %}