reverse() is not working - python

I am trying to pass the id through reverse. But it's not working. I'm getting this error
Reverse for 'reg.views.thanks' with arguments '(20,)' and keyword arguments '{}' not found.
Here is my views.py:
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.core.urlresolvers import reverse
from reg.models import registration, registrationform
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
def registration(request):
if request.method == 'POST':
form = registrationform(request.POST)
if form.is_valid():
data = form.save()
id = data.id
return thanks(request,id)
else:
form = registrationform()
return render_to_response('registration.html', {'form' : form}, context_instance=RequestContext(request))
def thanks(request, id):
p = get_object_or_404(registration, pk=id)
return render_to_response('thanks.html', {'reg' : p})
Here is my urls.py:
from django.conf.urls import patterns, include, url
url(r'^registration/$', 'reg.views.registration'),
url(r'^thanks/$', 'reg.views.thanks'),
url(r'^$','django.views.generic.simple.direct_to_template', {'template' : 'index.html'}),
)
Here is thanks.html:
<html>
<body>
<p>Thank you for registration mr.{{reg.username}}</p>
</body>
</html>
and I'm also showing my models.py:
from django.db import models
from django.forms import ModelForm
class registration(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class registrationform(ModelForm):
class Meta:
model = registration
Thanks.

from this links (django tutorial):
https://docs.djangoproject.com/en/dev/topics/http/urls/#django.core.urlresolvers.reverse
example:
def myview(request):
return HttpResponseRedirect(reverse('arch-summary', args=[1945]))
so your code goes to:
in urls.py:
url(r'^thanks/(?P<id>\d+)$', 'reg.views.thanks', name='my_thanks_url')
in your function:
return HttpResponseRedirect(reverse('my_thanks_url', args=[id]))

This line
return HttpResponseRedirect(reverse('reg.views.thanks', args=(id,)))
Is trying to construct a url to your view reg.views.thanks, with the id variable used as a parameter.
This line in urls.py
url(r'^thanks/$', 'reg.views.thanks'),
Does not have anywhere for that parameter to go.
The first thing that you need to figure out is whether you actually want to send an HTTP redirect to the browser to tell it to go to the 'thanks' page. If you really do, then you need a way to send that id in the URL. You can do it as part of the URL path itself, as #moguzalp suggests, or you can put it in the query string, like
/thanks/?id=12345
Or you can do other things, like stashing the id in the user's session, and pulling it out when they request the thanks page. That's a bit more complicated, though.
If you don't actually need to issue an HTTP redirect, then there's nothing stopping you from just calling the thanks() function from inside your view function, like this:
def registration(request):
if request.method == 'POST':
form = registrationform(request.POST)
if form.is_valid():
data = form.save()
id = data.id
return thanks(request, id)
else:
form = registrationform()
return render_to_response('registration.html', {'form' : form}, context_instance=RequestContext(request))
The URL won't change in the browser, but the correct ID will be used, and doesn't need to appear anywhere else, in the URL, the query parameters, or the session

Related

The view urlshort.views.page_redirect didn't return an HttpResponse object. It returned None instead

I'm making a url shortener with django. I have a form that has a long_url attribute. I'm trying to get the long_url and add it to a redirect view with a HttpResponseRedirect.
# Form
from .models import ShortURL
from django import forms
class CreateNewShortURL(forms.ModelForm):
class Meta:
model=ShortURL
fields = {'long_url'}
widgets = {
'long_url': forms.URLInput(attrs={'class': 'form-control'})
}
# View
def page_redirect(request, url):
if request.method == 'GET':
form = CreateNewShortURL(request.GET)
if form.is_valid():
original_website = form.cleaned_data['long_url']
return HttpResponseRedirect(original_website)
When I go to the link, it gives me The view urlshort.views.page_redirect didn't return an HttpResponse object. It returned None instead. Does anyone know why this is happening?
It is not returning because there is no valid form, you need to redirect to a form for the user to enter data first, you will then get that data from the form to perform your redirect. additionally because a user is returning data you will need to get the data from request.POST.
def page_redirect(request, url):
if request.method == 'GET':
form = CreateNewShortURL(request.POST)
if form.is_valid():
original_website = form.cleaned_data['long_url']
return HttpResponseRedirect(original_website)
return render(request,'template') # this is the form for the user to enter the url

Passing context to a Response and using it in a view

I am working on a web app and I want to use HttpResponse or HttpResponseRedirect instead of render. But I dont know hoe to pass context in response as it does not have context parameter like render. And also how to use the passed context in the url or view ?
Here is my view:
#login_required
def view_task_description(request):
if request.method == 'POST':
task_description = GetTaskDescription(data=request.POST, user=request.user)
if task_description.is_valid():
obj = GetTaskDescription.get_task_description(task_description)
return render(request, 'todoapp/task_desc.html', context={'description': obj[0].description})
return render(request, 'todoapp/select_task_description.html', context={'view_tasks': GetTaskDescription(user=request.user)})
I want to use Redirect or ResponseRedirect with the context instead of the render that I am returning if my form is valid. Basically render still shows the response as a POST method and I want the response to be a GET. How can I do so ? Thanks.
You can simply create a new view for that. Then link it to the existing view using redirect. For example:
# view
from django.shortcuts import get_object_or_404
#login_required
def get_task_description(request, pk):
obj = get_object_or_404(TaskDescriptionModel, pk=pk)
return render(request, 'todoapp/task_desc.html', context={'description': obj.description})
# url
url(r'^some_path/(?P<pk>[0-9]+)/$', get_task_description, name="get_task_description")
# linking to existing view
from django.shortcuts import redirect
...
if task_description.is_valid():
obj = GetTaskDescription.get_task_description(task_description)
return redirect('get_task_description', pk=obj[0].pk) # <-- Pointing the new view

DJANGO - Redirect to different page from POST with data

I am trying to have a simple form that once filled, will direct to a different webpage or remain on the same page if invalid. The page should have a text box and submit form and once a user enters anything it should direct you to a separate page.
My directory structure is as follows:
appName/
app/
forms.py
urls.py
views.py
templates/
app/
goodbye.html
name.html
library.html
thanks.html
appName/
settings.py
urls.py
My app/urls.py is as follows:
from django.conf.urls import url
from . import views
app_name = 'app'
urlpatterns = [
url(r'^$', views.index2, name = 'index'),
url(r'^hello/$', views.hello, name = 'hello'),
url(r'^goodbye/$', views.goodbye, name = 'goodbye'),
#url(r'^library$', views.library, name = 'library'),
url(r'^library/$', views.library, name = 'library'),
url(r'^library/(?P<book_id>[0-9]+)/$', views.book, name = 'book'),
url(r'^getname/$', views.get_name, name = 'get_name'),
url(r'^your-name/$',views.get_name, name='get_name'),
url(r'^thanks/$',views.say_thanks,name='thanks'),
#url(r'^thanks/(?P<name_id>[a-zA-Z]+)/$', views.say_thanks,name='thanks'),
]
My forms.py is :
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label = 'Your name', max_length=100)
My app/views.py is:
from django.http import HttpResponse
from django.template import loader
from django.shortcuts import render
from django.http import HttpResponseRedirect
#forms
from .forms import NameForm
# Create your views here.
def index2(request):
return HttpResponse("hello world")
def hello(request):
text = """<h1>Welcome to my app! </h1>"""
return HttpResponse(text)
def goodbye(request):
template = loader.get_template("app/goodbye.html")
context = {
'output' : 'This is output from goodby views.py request handler'
}
return HttpResponse(template.render(context,request))
def library(request):
template = loader.get_template("app/library.html")
context = {
'output' : 'Welcome to the libary!!'
}
return HttpResponse(template.render(context, request))
def book(request, book_id):
return HttpResponse("You're looking at book %s. " % book_id)
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
#process the data in form.cleaned_data as required
locationGo = "/thanks/"
template = loader.get_template("app/thanks.html")
return HttpResponse(template.render({'name':'name'},request))
else:
form = NameForm()
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
def say_thanks(request):
template = loader.get_template("app/thanks.html")
return HttpResponse(template.render({'name': 'name'},request))
My templates include:
name.html :
<form action = "/getname/" method = "post">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit" />
</form>
goodbye.html
<h1>Goodbye to Template Romance</h1>
Go Back
thanks.html
Thanks {{name}}!
What I would like is for:
A user to visit to : website.com/getname/ to show the name.html file (which it does)
If a user hits submit to stay on the same page (website.com/getname/) (which it doesn't - it gives: ValueError at /getname/ ->The view app.views.get_name didn't return an HttpResponse object. It returned None instead.
If a user enters in the submit field, to be redirected to website.com/thanks/ (which it sort of does. It currently loads the thanks.html template, but the URL stays on website.com/getname/)
Inside the get_name(request): function, the POST and GET if...else doesn't seem to be firing based on the Submit button, and it doesn't seem to be loading the correct page, OR change the current URL address once it gets processed. I have tried using HttpRedirect() which works, however, I would also like to pass the forms data (which is another issue).
Any suggestions would be a big help!
Your first problem is that you are not returning a response when the request method is post and the form is invalid. You can fix that by changing the indentation of your view, so that you always return a response at the end of your view.
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
...
else:
form = NameForm()
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
If you want to redirect to the /thanks/ view, then you can use the redirect shortcut.
if form.is_valid():
return redirect('thanks')
Note that it isn't possible to redirect and pass the form data (see this question for an explanation). You should do any processing you want with the data before redirecting. You could use the messages framework to create a message 'Thanks <name>' before redirecting.
This works because you have name='thanks' in your url pattern.
You can simplify your views by using the render shortcut. Instead of
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
you can simply do:
return render(request, "app/name.html", context)
Remember to add the imports for the shortcuts:
from django.shortcuts import redirect, render

Django 1.9.4 Get input data from form to show into a different template

Here is my code that I believe pertains to this situation. I'm sorry, I'm new to django.
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import SearchForm
def result_one(request):
return render(request, "testresult.html", {})
def get_results(request):
if request.method == 'POST':
form = SearchForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/result/')
else:
form = SearchForm()
return render(request, 'index.html', {'form': form})
urls.py
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^search/$', "search.views.get_results"),
url(r'^result/$', "search.views.result_one"),
]
forms.py
from django import forms
class SearchForm(forms.Form):
client_group_number=forms.IntegerField(label='Group Number', widget=forms.TextInput(attrs={'placeholder': 'Group Number'}))
From my understanding, what I believe should happen is that an input will be put into a html page. When the user hits submit, the input gets saved into forms.py as data. This data gets manipulated in views.py which gets displayed in a different html page. (I hope this is correct)
What I want it to do is take in an input for client_group_number(in forms.py) from index.html(for example: 123), that can be accessed in views.py and displayed in another html template that I have called testresult.html, which would display Group Number = 123 (the 123 coming from either the forms.py or views.py).
This might be a very simple thing to accomplish and I apologize if it is, but I can't seem to find what I need on the internet.
Django validate the form input data in the cleaned_data dictionary. You would need to pass this to the new template either as arguments in the redirect or using session. Here is one simple example to give you an idea, there are probably better ways.
if form.is_valid():
group_number = form.cleaned_data["client_group_number"]
HttpResponseRedirect("/result/?group_number=" + group_number)

How to use initialize FormModel with request.post and model instance.

So I basically have this code:
#render_to('hello/home.html')
def home(request):
info = Info.objects.get(pk=1)
if request.method == "POST":
form = InfoForm(request.POST, instance=info)
else:
form = InfoForm(instance=info)
return {"info": info, "form": form}
aaand it doesn't work as I guessed it would be.
If I initialize form with ONLY either model instance or POST, it works, but not when both.
Is there a (nice?) way to create form with data populated from model instance, and update it with data from request.POST?
The code you are writing is already in the framework.
urls.py
from django.views.generic import UpdateView
from myapp.forms import InfoForm
urlpatterns = patterns('',
url(r'^info/(?P<pk>[-_\w]+)/update/$', UpdateView.as_view(model= Info,template_name="hello/home.html",form_class=InfoForm), name='info_update'),
)
# you might need to include a success url in the **kwargs i.e. success_url="/thankyou/"

Categories