Django NoReverseMatch in form redirect - python

I am getting the following error:
NoReverseMatch at /lld/new/
Reverse for 'display_lld' with arguments '()' and
keyword arguments '{'slug': u'stack-overflow-new-document'}' not found.
0 pattern(s) tried: []
I can't get to the bottom of it, though I think it has something to do with either my url regex or the document.slug variable passed to the index.html template in views.py.
views.py:
from django.shortcuts import get_object_or_404, render, redirect
from .models import Document
from .forms import DocumentForm
def index(request):
document_list = Document.objects.order_by('-date_updated')
context = {'document_list': document_list}
return render(request, 'lld/index.html', context)
def display_lld(request, slug):
document = get_object_or_404(Document, slug=slug)
return render(request, 'lld/display_lld.html', {'document': document})
def new_lld(request):
if request.method == "POST":
form = DocumentForm(request.POST)
if form.is_valid():
document = form.save(commit=False)
document.save()
return redirect('display_lld', slug=document.slug)
else:
form = DocumentForm()
return render(request, 'lld/new_lld.html', {'form': form})
site urls.py:
urlpatterns = [
url(r'^lld/', include('lld.urls', namespace="lld")),
url(r'^admin/', include(admin.site.urls)),
]
app urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
# example: /lld/
url(r'^$', views.index, name='index'),
# example: /lld/new/
url(r'^new/$', views.new_lld, name='new_lld'),
# ex: /lld/customername-projectname/
url(r'^(?P<slug>([\w-]+))/', views.display_lld, name='display_lld'),
]
index.html:
{% if document_list %}
<ul>
{% for document in document_list %}
<li>{{ document.customer }} / {{ document.title }}</li>
{% endfor %}
</ul>
{% else %}
<p>No documents are available.</p>
{% endif %}
Create New LLD
The form creates the new document fine, it shows up in the admin. But when I click on the forms save button it brings up the NoReverseMatch error rather than redirecting back to the created document. The newly created document is listed on the index page and I can navigate to it by clicking on it's link there, it just appears to throw the error in the form redirect.

When calling redirect, you have left out the lld namespace. You need to include the namespace when you use redirect or reverse, the same way as you already do when you use the {% url %} tag in your templates:
return redirect('lld:display_lld', slug=document.slug)

from django.core.urlresolvers import reverse
return redirect(reverse('lld:display_lld', args=[document.slug]))

Related

Django UserCreationForm not responding when button clicked with input in fields

I'm having trouble getting my register application in Django to work. I am using the built-in UserCreationForm form. I can go to the URL and the form shows up but when I put info into the fields and click the submit button nothing happens. It should pop up an error screen saying "missing the csrf_field" (I know this because I'm following TechWithTim's tutorial and that's what happens to him). But when I click the "Register" button nothing happens.
views.py:
from django.shortcuts import render
from django.contrib.auth.forms import UserCreationForm
# Create your views here.
def register(response):
form = UserCreationForm()
return render(response, "register/register.html", {"form":form})
register.html:
{% extends "main/base.html" %}
{% block title %}Create an Account{% endblock %}
{% block content %}
<form method="POST" class="form-group">
{{form}}
<button type="submit" class="btn btn-success">Register</button>
</form>
{% endblock %}
urls.py:
from django.contrib import admin
from django.urls import path, include
from register import views as v
urlpatterns = [
path('', include("main.urls")),
path("register/", v.register, name="register"),
path('admin/', admin.site.urls),
]
main/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("<int:id>", views.index, name='index'),
path("", views.home, name='home'),
path("create/", views.create, name='create'),
]
I added the application to my settings.py file as well.
This is my first question on here and I tried to format it properly so sorry if I didn't
In order for Django to recieve the data the user entered in the form, you need to pass the request's POST data to the form, if it exists. That would look like this:
form = UserCreationForm(response.POST)
But note that response.POST will not exist if it's not a POST request. (For example, if the user is viewing the form for the first time.) The Django docs have an example of how to process form data.
Alternatively, you can look at the tutorial you're using, which has an example of how to get the POST data out of the form:
# views.py
from django.shortcuts import render, redirect
from .forms import RegisterForm
# Create your views here.
def register(response):
if response.method == "POST":
form = RegisterForm(response.POST)
if form.is_valid():
form.save()
return redirect("/home")
else:
form = RegisterForm()
return render(response, "register/register.html", {"form":form})
(Source.)

Not returning html page for viewing - django

error message --> The view orders.views.charge didn't return an HttpResponse object. It returned None instead. any reason why my charge.html isn't working?
views,py
import time
import stripe
from django.conf import settings
from django.shortcuts import render
from django.urls import reverse
def charge(request):
if request.method == 'POST':
charge = stripe.Charge.create(
amount=500,
currency='eur',
description='A Django charge',
source=request.POST['stripeToken']
)
template = "orders/charge.html"
return render(request, template)
charge.html
{% extends "fuisce/base.html" %}
{% block content %}
<div class="container mt-5 text-center">
<h2 class="text-center">Thanks, you for your Orders</h2>
My Orders
</div>
{% endblock %}
urls.py
from django.urls import path
from . import views
from orders import views as order_views
from users import views as user_views
urlpatterns = [
path('checkout/', order_views.checkout, name='checkout'),
path('charge/', order_views.charge, name='charge'),
path('orders/', order_views.orders, name='user_orders'),
path('add_user_address/', user_views.add_user_address, name='add_user_address'),
]
Bring the returning code from your view outside the if condition if you want it to return on GET requests.
def charge(request):
if request.method == 'POST':
charge = stripe.Charge.create(
amount=500,
currency='eur',
description='A Django charge',
source=request.POST['stripeToken']
)
template = "orders/charge.html"
return render(request, template)

How to render a html page without view model?

Is it possible to render an HTML page without having a view model in Django if a page is going to display only static HTML?
Basically, I want to delete an issue from a webpage and then show a 'successfully deleted' static HTML page after deleting.
But I got blew error, anyone could help?
NoReverseMatch at /project/1/issue/14/delete_issue/
Reverse for 'nice_delete.html' not found. 'nice_delete.html' is not a valid view function or pattern name.
view.py
def delete_issue(request,project_id,issue_id):
if not request.user.is_staff or not request.user.is_superuser:
raise Http404
issue = get_object_or_404(Issue,id=issue_id)
issue.delete()
return redirect(reverse('project:issue_tracker:nice_delete.html'))
urls.py
urlpatterns =[
path('',views.list_of_issue,name='list_of_issue'),
path('<int:issue_id>/',views.issue_detail,name='issue_detail'),
path('<int:issue_id>/comment',views.add_comment,name='add_comment'),
path('new_issue/',views.new_issue,name='new_issue'),
path('<int:issue_id>/edit_issue/',views.edit_issue,name='edit_issue'),
path('<int:issue_id>/delete_issue/',views.delete_issue,name='delete_issue'),
]
nice_delete.html
{% extends 'base.html' %}
{% block content %}
<p>Successfully delete this issue</p>
{% endblock %}
You can use TemplateView for this. Just add to your urlpattern:
from django.views.generic import TemplateView
urlpatterns =[
path('',views.list_of_issue,name='list_of_issue'),
path('<int:issue_id>/',views.issue_detail,name='issue_detail'),
path('<int:issue_id>/comment',views.add_comment,name='add_comment'),
path('new_issue/',views.new_issue,name='new_issue'),
path('<int:issue_id>/edit_issue/',views.edit_issue,name='edit_issue'),
path('<int:issue_id>/delete_issue/',views.delete_issue,name='delete_issue'),
path('deleted/', TemplateView.as_view(template_name="nice_delete.html"), name='success_deletion'),
]
And use success_deletion url in delete_issue view for redirection:
def delete_issue(request,project_id,issue_id):
if not request.user.is_staff or not request.user.is_superuser:
raise Http404
issue = get_object_or_404(Issue,id=issue_id)
issue.delete()
return redirect('success_deletion')

How can I call multiple views in one url address in Django?

I'm trying to show forms defined by new_measurement on index.html, but I only manage to get IndexView() to work. I tried various combinations between IndexView() and new_measurement(), but those didn't work out at all. I know that IndexView() doesn't pass anything related to new_measurement(), and new_measurement() isn't called, which is the core of my problem. I'd really appreciate if someone more experienced with Django could tell me what I could, or should do. Thank you.
Here's my views.py:
from django.shortcuts import render
from django.utils import timezone
from .models import Measurement
from .forms import MeasurementForm
from django.views import generic
class IndexView(generic.ListView):
model = Measurement
context_object_name = 'measurement_list'
template_name = 'index.html'
queryset = Measurement.objects.all()
def new_measurement(request):
if request.method == "POST":
form = MeasurementForm(request.POST)
if form.is_valid():
measurement = form.save(commit=False)
measurement.measurement_date = timezone.now()
measurement.save()
else:
form = MeasurementForm()
return render(request, 'index.html', {'form': form})
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
]
forms.py:
class MeasurementForm(forms.ModelForm):
class Meta:
model = Measurement
fields = ('measurement_value', 'measurement_unit')
index.html:
{% extends "base.html" %}
{% block content %}
<h1>Climate Measurement Tool</h1>
<h2>Add a new measurement</h2>
<form method="POST" class="post-form">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save">Add</button>
</form>
<h2>Measurements</h2>
{% if measurement_list %}
<ul>
{% for measurement in measurement_list %}
<li>
<p>{{ measurement }}</p>
</li>
{% endfor %}
</ul>
{% else %}
<p>No measurements yet</p>
{% endif %}
{% endblock %}
You can't map multiple views in one url but you can do mutiple works in one view.
update your views.py as you can see that I am sending (querylist and form) both in that view
views.py
def new_measurement(request):
if request.method == "POST":
form = MeasurementForm(request.POST)
if form.is_valid():
measurement = form.save(commit=False)
measurement.measurement_date = timezone.now()
measurement.save()
else:
form = MeasurementForm()
qs = Measurement.objects.all()
context = {'form': form, 'measurement_list': qs}
return render(request, 'index.html', context)
update urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.new_measurement, name='index'),
]
You can't call 2 views for one url. basically each url has to be linked to one view and that's something you can't really change.
But if you want your code to be cleaner and have multiple functions, you can call them in your view, basically what you can do is to make a view and call it when a url or even more than one url has been used and in that view decide which function to use
Example:
def god_view(request):
if request.method == "POST"
return post_func(request)
return get_func(request)
This is a very simple example but you can do so many other things.
It is not possible to have more views in one url, but you can simulate it. I did it like a view and in the template of this view was javascript which loaded the second view with the response of AJAX and filled the belonging element with the second view's content. The second view was not whole template but it started with some div tags which were placed into the first template. I'll try to give you an example
views
def first_view(request):
return render(
request,
'first_template.html',
{
'first_content': 'Some heavy content'
})
def second_view(request):
return render(
request,
'second_template.html',
{
'second_content': 'Some heavier content!'
})
first_template.html
...
<body>
<div id="1">
{{ first_content }}
</div>
<div>
... loading ...
</div>
<script>
window.onload = function() {
$.ajax({
url: {% url 'to_second_view' %},
method: 'GET',
success: function(response) {
$('#2').html(response);
}
})
}
</script>
</body>
...
second_template.html
<div>
{{ second_content }}
</div>
If you're using cbv you can override the get_template_names method for any view that inherits TemplateResponseMixin and return a list of string which are searched in order until one matches or ImporperlyConfigured is raised. For example:
class SomeView(TemplateResponseMixin):
...
def get_template_names(self):
if self.request.method == "POST":
return ['post_template.html']
else:
return ['template.html']
Instead of generic.ListView you can try with rest_framework.views.APIView
from rest_framework.views import APIView
class IndexView(APIView):
def post(self, request: Request):
form = MeasurementForm(request.POST)
if form.is_valid():
measurement = form.save(commit=False)
measurement.measurement_date = timezone.now()
measurement.save()
return render(request, 'index.html', {'form': form})
def get(self, request: Request):
form = MeasurementForm()
return render(request, 'index.html', {'form': form})
This gives you more control on the APIs you call. Also you can raise/return error when you call your API using incorrect methods (PUT, PATCH)

NoReverseMatch pattern not found

Having trouble figuring out why I keep getting the NoReverseMatch.
app/url.py
from django.conf.urls import url, patterns
from . import views
urlpatterns = patterns('',
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<contact_id>\d+)/detail/$', views.details, name='details'),
)
views.py
from django.core.urlresolvers import reverse
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.http import Http404
from django.views import generic
from django.template import RequestContext, loader
from .models import Person
# Create your views here.
class IndexView(generic.ListView):
template_name = 'ContactManager/index.html'
context_object_name = 'contact_list'
def get_queryset(self):
return Person.objects.order_by('lname')
def details(request, contact_id):
contact = get_object_or_404(Person, id=contact_id)
return render(request, 'ContactManager/details.html', {'contact': contact})
# class DetailView(generic.ListView):
# model = Person
# context_object_name = 'contact'
# template_name = 'ContactManager/details.html'
#
# def get_queryset(self):
#
template index.html
{% if contact_list %}
<ul>
{% for contact in contact_list %}
<li>
{{ contact.fname }} {{ contact.lname }}
</li>
{% endfor %}
</ul>
{% else %}
<p>You don't have any contacts currently.</p>
{% endif %}
The error I am getting:
Reverse for 'details' with arguments '()' and keyword arguments '{'contact_id': 1}' not found. 1 pattern(s) tried: ['$(?P<contact_id>\\d+)/detail/$']
I have tried using generic views and a host of arguments in the {% url ... %}
Any help would be much appreciated.
I think that details url pattern has a mistake, in error message appears one tried pattern, started and ended by $ sign:
1 pattern(s) tried: ['$(?P\d+)/detail/$']
check your pattern that is equal to or no:
^(?P<contact_id>\\d+)/detail/$
if this is correct check your urls file that included contact urls and if is similar below:
url('^$', include(ContactManager.urls, namespace='contact'))
remove $ sign at end of prefix-pattern:
url('^', include(ContactManager.urls, namespace='contact'))
Note that this error can also arise if you do not define name in your urlpatterns.
Doing something like
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^error_containing_view/$', views.error_containing_view, name='error_containing_view'),
]
in your app's urls.py would fix the error.

Categories