Passing context to a Response and using it in a view - python

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

Related

Django: Can I use HttpResponseRedirect() and give it any arguments to be rendered on this page? [duplicate]

This question already has answers here:
How to pass extra_context when redirecting in Django
(2 answers)
Closed 4 years ago.
I have a Django form which upon validation I want to redirect to a success page. I start at "localhost/upload", submit my form, if it is validated I want to go to localhost/upload/success. The following code works, I just want to be able to pass a context dictionary with some variables in there to render to the page. I can only do this using (hashed out in the views.py code below)
return render(request, 'results/success.html', context)
but this returns to localhost/upload, but with my success.html template - i want to go to upload/success.
Here is my code:
views.py:
#login_required(login_url='/')
def upload(request):
""" Upload panel or results.
"""
if request.method == 'POST':
paneluploadform = PanelUploadForm(request.POST, request.FILES)
if paneluploadform.is_valid():
paneluploadform.upload()
context = {'hi': 'helloasdgja'}
# return render(request, 'results/success.html', context)
return HttpResponseRedirect('success')
else:
# print(paneluploadform.errors.as_text)
pass
else:
paneluploadform = PanelUploadForm()
context = {'paneluploadform': paneluploadform}
return render(request, 'results/upload.html', context)
#login_required(login_url='/')
def success(request):
""" Success view
"""
return render(request, 'results/success.html')
urls.py:
from django.conf.urls import url
from .views import *
urlpatterns = [
url(r'^upload/$', upload),
url(r'^upload/success/', success)
]
I can use the hashed out return render() line to give my test context, but this returns to "localhost:8000/upload"
I want to go to localhost:800/upload/success, but get information from upload view and redirect to upload/success. Can I pass a context arg to HttpResponseRedirect or is there a way around this?
Session variables are useful for passing information between pages/views.
https://docs.djangoproject.com/en/dev/topics/http/sessions/
Ian Clelland does a good job of highlighting your options here:
https://stackoverflow.com/a/8931063/4928578

Django: How to redirect with arguments

After submit a form, I want to redirect to an specific view passing one flag=True in order to activate a popup like:
def view1(request):
if request.method == 'POST':
form = Form(request.POST)
if form.is_valid():
form.save()
return redirect('new_view') # Here I need to send flag=True
else:
form = Form()
return render(request, 'template.html', {'form': form})
How can I do this?
It's not quite clear on what you mean by arguments if it should be in the query string or arguments to a view.
Either way, below is both solutions;
redirect accepts args and kwargs
redirect('new_view', flag='show') # This is the argument of a view
or
redirect('{}?flag=True'.format(reverse('new_view'))
Then you can access it in the view like so
show_flag = bool(request.GET.get('flag', False))
for a given url pattern such as
url(r'^random/(?P<arg1>[0-9]+)/(?P<arg2>[0-9]+)/$', views.random, name="urlname")
or
url(r'^argfree/', views.random2, name="urlname2
from django.http import HttpResponseRedirect
from django.urls import reverse
def view(request):
# do your thing
if something:
return HttpResponseRedirect(reverse("urlname", args=["this_is_arg1", "this_is_arg2"]))
else:
return HttpResponseRedirect(reverse("urlname"))
There is a django-url-params module to help you in this situation. Just add
request.cparam = {'flag': True}
return param_redirect(request, viewname)
from django.urls import reverse
response = redirect(f"{reverse('search')}?query='How to redirect with arguments'")

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

The view app.views.model didn't return an HttpResponse object

This is my views.py file. i am on the way to generate xml file, The data i am getting from mysql. First time its working but i make some changes then i cant remember what i did now it s not working ...
in the views.py
def MessageHeaderModel2(request):
if request.method == "POST":
form = MessageHeaderForm(request.POST)
if form.is_valid():
DDEX_Party_Id = request.POST.get('DDEX_Party_Id',None)
data = serializers.serialize("xml", MessageHeaderModel2.objects.all())
with open("file.xml", "w") as out:
xml_serializer.serialize(MessageHeaderModel2.obj ects.all(), stream=out)
The error now i am gettin is
>Exception Type:ValueError
Exception Value:The view app.views.MessageHeaderModel2 didn't return an HttpResponse object.
Like stated in the error, your view isn't sending any response to the client.
Add at the end of your view a line like :
return render(request, 'template.html')
Or any other response, that you need
You in fact are not returning an HttpResponse object!
Django views must return an instance of HttpResponse so at the end of your view:
from django.http import HttpResponse
def view(request):
...
return HttpResponse("the page content")
You can also return may other subclasses of HttpResponse, see the documentation for a list.
You can also use some of the shortcut functions to render a page using the django templating system, again the documentation is helpful here, but briefly:
from django.shortcuts import render_to_response
def view(request):
...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
A complete example using your code from above:
def view(request):
if request.method == "POST":
form = MessageHeaderForm(request.POST)
if form.is_valid():
DDEX_Party_Id = request.POST.get('DDEX_Party_Id',None)
data = serializers.serialize("xml", MessageHeaderModel2.objects.all())
with open("file.xml", "w") as out:
out.write(data)
return HttpResponse(data)
else:
# return error response?
return HttpResponseNotAllowed(['POST'])
You are not returning anything so that's why you have such an error...
You can also for example return Success value or redirect to other view..

csrf token Follow up

Hello and thank you in advance. This is a follow up question from the following thread (not sure if I should have posted there or started a new thread...:
CSRF token missing or incorrect even though I have {% csrf_token %}
I am not sure what I need to do with the code to make csrfContext work. I am trying to use ModelForm to collect data to a model and write it to a MYSQL table. I am gettingthe error:
Reason given for failure:
CSRF token missing or incorrect.
Here is the code:
from django.shortcuts import render_to_response
from djengo.template import RequestContext
from django.http import HttpResponse, HttpRequest, HttpResponseRedirect
from acmetest.models import Player
from acmetest.models import PickForm
csrfContext = RequestContext(request)
return render_to_response('makepick.html', csrfContext)
def playerAdd(request, id=None):
form = PickForm(request.POST or None,
instance=id and Player.objects.get(id=id))
# Save new/edited pick
if request.method == 'POST' and form.is_valid():
form.save()
return HttpResponseRedirect('/draft/')
return render_to_response('makepick.html', {'form':form})
Again,
Thank you for your help!
dpbklyn
Update your code thusly:
from django.shortcuts import render
# from djengo.template import RequestContext <- this is not valid.
These two lines, as Yuji pointed out, are not valid python, and in addition they are not necessary if you use the render shortcut.
# csrfContext = RequestContext(request)
# return render_to_response('makepick.html', csrfContext)
Modify your return line:
# return render_to_response('makepick.html', {'form':form})
return render(request,'makepick.html',{'form':form})
I'm assuming we're talking about the playerAdd view - you need to pass RequestContext to the response there.
def playerAdd(request, id=None):
form = PickForm(request.POST or None,
instance=id and Player.objects.get(id=id))
# Save new/edited pick
if request.method == 'POST' and form.is_valid():
form.save()
return HttpResponseRedirect('/draft/')
return render_to_response('makepick.html', RequestContext(request, {'form':form}))
The first lines in your code are hard to understand and doesn't even appear to be valid python. You can't use return from outside a function block.

Categories