Django: How to redirect with arguments - python

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'")

Related

Why we write this, form = StudentForm(request.POST) in django?

This is my views function,
def studentcreate(request):
reg = StudentForm()
string = "Give Information"
if request.method == "POST":
reg = StudentForm(request.POST)
string = "Not Currect Information"
if reg.is_valid():
reg.save()
return render('http://localhost:8000/accounts/login/')
context = {
'form':reg,
'string': string,
}
return render(request, 'student.html', context)
Here first we store form in reg variable then also we write reg = StudentForm(request.POST) why?
acutally why we write this?
I can't tell you why you are writing this. Maybe only you know. It does not make much sense. I would recommend reading the Django documentation on this at https://docs.djangoproject.com/en/4.0/topics/forms/#the-view
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import NameForm
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
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
You read from data if the request is a POST. Otherwise, return an empty form.
You could think of the "request.POST" as a parameter passed onto the form in the view. This tells the view that the form mentioned has POST data from the form in name.html. Otherwise it is just an empty form.

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

Post method not working after redirect in Django

I am trying to create a system where certain pages can't be accessed unless the request is from a specific location. I currently have everything working except after the location is checked and the request is redirected to the next view, the form on that next view isn't posting properly. It's still trying to post the location data form.
You'll see what I mean more in my views.py:
def add(request):
if request.method == 'POST':
form = StudentModelForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
form = StudentModelForm()
context_data = {'form': form}
return render(request, 'add.html', context_data)
def location_check_add(request):
if request.method == 'POST' and 'lat' in request.POST:
user_lat = request.POST.get('lat')
user_lon = request.POST.get('lon')
if good_location(user_lat,user_lon):
return add(request)
else:
return render(request, 'location.html')
return render(request, 'checking.html')
So I'm trying to redirect to the add() view if good_location is true. It redirects properly but then when a user tries to post the form on add.html django thinks it's submitting the form in location_check_add again.
Edit: Adding urls.py for reference
import users.views
urlpatterns = patterns('',
url(r'^$', users.views.index, name = 'index'),
url(r'^admin/', include(admin.site.urls)),
url(r'^add/', users.views.location_check_add, name = 'add'),
)
You need to redirect, not just call the view.
if good_location(user_lat,user_lon):
return redirect('add')
Alright! After a lot of documentation searching and googling I found out about Django's sessions feature. Documentation here:
Documentation
In the end my code ended up looking like:
def add(request):
if request.session.get('at_work', False):
if request.method == 'POST':
form = StudentModelForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
form = StudentModelForm()
context_data = {'form': form}
return render(request, 'add.html', context_data)
else:
return redirect(location_check_add)
def location_check_add(request):
if request.method == 'POST' and 'lat' in request.POST:
user_lat = request.POST.get('lat')
user_lon = request.POST.get('lon')
if good_location(user_lat,user_lon):
request.session['at_work'] = True
return redirect(add)
else:
return render(request, 'location.html')
return render (request, 'checking.html')
Basically I just passed around the session variable "at_work" to make sure the location was correct before rendering the page in the add() view. Then I was able to use the regular redirect function since I could have a url directed at add() in urls.py without people getting around the location check.

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.

reverse() is not working

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

Categories