Modal forms and Django URLs, how to work? - django

html
<form action="{% url 'sp_feedback' %}" method="post">
url
url(r'^feedback/$', views.post_feedback, name="sp_feedback"),
views:
return HttpResponseRedirect("")
In using modal forms, how do you, after hitting submit, return to the page?
In my current setup, the browser redirects to nothing. I'm completely confused on what to put in the url regular expressions.

In my current setup, the browser redirects to nothing.
Because you're redirecting to an empty URL:
return HttpResponseRedirect("")
You've to redirect to the url of the page:
return HttpResponseRedirect('/feedback/')
But it is rather better and convenient to use the redirect() shortcut. Because you can pass it the name of the url and Django will automatically make the redirect to the associated url.
Example:
return redirect('sp_feedback')
It is a good practice to avoid using hardcoded urls in your application.
UPDATE
Since you mention that this form is on every page and you'd like to redirect the user back to that page, here's one solution:
Use request.META['HTTP_REFERER'] in your form view to get the referring page, then use that value to make the redirect:
redirect_to = request.META.get('HTTP_REFERER', '/') # if HTTP-Referer header is not present, just redirect to homepage
return HttpResponseRedirect(redirect_to)

Related

html - redirect to new url after form submission (django site)

I am trying to make a button redirect the user to a new url after they submit a form. This is how it is right now, and it works properly and all the data gets sent to the django database.
<form method='POST' action='' class="col-md-6 col-md-offset-7" style="background-color: lightgreen; border-radius: 10px">
However, when I change the action to
action="{% url 'ridesharing:request-success' %}",
the redirect works, but the data does not go to my django database.
What is going on here?
You seem to have some confusion here. The action of the form is where the browser will send the data. Obviously, if you don't point that at the view which actually processes the data, then it won't be saved.
To redirect after a post, your view should return a redirect.
When you declare a form with an empty action attribute:
<form method='POST' action=''>
the POST data will be sent to the same URL. This is useful because if there is some error in the form, it's easy to re-display it with all fields filled with values entered by the user. Then, when the form becomes valid, a redirect is done to the confirmation page.
When you declare your form that way:
<form method='POST' action='{% url 'ridesharing:request-success' %}'>
The data entered by the user in the form will be sent to the view request-success. But this view probably only render the template of the confirmation page. If you want to correctly handle data from the form, you have to set action attribute of your <form> to the same view, or easier, keep it empty.
I do not understand why Daniel Roseman's post isnt accepted as the answer. It helped me when I wanted to redirect a create form to its update form.
Basically in the view of the app I defined the get_success_url to reverse_lazy to the data-update.
def get_success_url(self):
return reverse_lazy('app_name:data-update')
Just replace the 'app_name:data-update' with the appropriate url.

Dynamic redirect url after login [duplicate]

I'm trying to build a simple website with login functionality very similar to the one here on SO.
The user should be able to browse the site as an anonymous user and there will be a login link on every page. When clicking on the login link the user will be taken to the login form. After a successful login the user should be taken back to the page from where he clicked the login link in the first place.
I'm guessing that I have to somehow pass the url of the current page to the view that handles the login form but I can't really get it to work.
EDIT:
I figured it out. I linked to the login form by passing the current page as a GET parameter and then used 'next' to redirect to that page. Thanks!
EDIT 2:
My explanation did not seem to be clear so as requested here is my code:
Lets say we are on a page foo.html and we are not logged in. Now we would like to have a link on foo.html that links to login.html. There we can login and are then redirected back to foo.html.
The link on foo.html looks like this:
<a href='/login/?next={{ request.path }}'>Login</a>
Now I wrote a custom login view that looks somewhat like this:
def login_view(request):
redirect_to = request.REQUEST.get('next', '')
if request.method=='POST':
#create login form...
if valid login credentials have been entered:
return HttpResponseRedirect(redirect_to)
#...
return render_to_response('login.html', locals())
And the important line in login.html:
<form method="post" action="./?next={{ redirect_to }}">
So yeah thats pretty much it, hope that makes it clear.
You do not need to make an extra view for this, the functionality is already built in.
First each page with a login link needs to know the current path, and the easiest way is to add the request context preprosessor to settings.py (the 4 first are default), then the request object will be available in each request:
settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.request",
)
Then add in the template you want the Login link:
base.html:
Login
This will add a GET argument to the login page that points back to the current page.
The login template can then be as simple as this:
registration/login.html:
{% block content %}
<form method="post" action="">
{{form.as_p}}
<input type="submit" value="Login">
</form>
{% endblock %}
To support full urls with param/values you'd need:
?next={{ request.get_full_path|urlencode }}
instead of just:
?next={{ request.path }}
This may not be a "best practice", but I've successfully used this before:
return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
Django's built-in authentication works the way you want.
Their login pages include a next query string which is the page to return to after login.
Look at http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.login_required
I linked to the login form by passing the current page as a GET parameter and then used 'next' to redirect to that page. Thanks!
I encountered the same problem. This solution allows me to keep using the generic login view:
urlpatterns += patterns('django.views.generic.simple',
(r'^accounts/profile/$', 'redirect_to', {'url': 'generic_account_url'}),
)
In registration/login.html (nested within templates folder) if you insert the following line, the page will render like Django's original admin login page:
{% include "admin/login.html" %}
Note: The file should contain above lines only.
See django docs for views.login(), you supply a 'next' value (as a hidden field) on the input form to redirect to after a successful login.
You can also do this
<input type="hidden" name="text" value="{% url 'dashboard' %}" />

Add query string to url in Django

I have a form which sends a POST request and returns a page. The url of this page is defined like this
(r'^result/', 'main.views.eval_form'),
and in the browser the url looks like
mysite.com/main/result
But I also have the url working with a Get Request so the user could save the url and not have to use the form, ie:
mysite.com/main/result?name=Tom&color=blue&etc=etc
Now is there a way to alter the url in the browser after the user uses the form, to include the query string by default? So that the user can copy the url and always return to result?
Thank you!
Change the method attribute of the <form> tag:
<form action="/main/result/" method="GET">
...
</form>
You could do a HttpResponseRedirect to the url with the prefilled querystring from the Post view.
Make sure you don't submit it twice or create an infinite loop.
return HttpResponseRedirect("/result?name={}&color={}&etc={}".format(name, color, etc))
Another way would be to fill your querystring with jQuery or Javascript from the template.
Myself I would take catavaran's approach
If you want to achieve this, you should alter your view to deal with both post and get request.
code may be like this:
def result(request):
name = request.REQUEST.get("name")
but request.REQUEST is deprecated since django 1.7
def result(request):
if request.method == "GET":
name = request.GET.get("name")
if request.method == "POST":
name = request.POST.get("name")

Django: calling view function without url mapping

How do I pass information from an HTML form to my Python code, without having to specify a url mapping? For example, the following code sends data from the form in my 'index.html' template, to the 'myview' mapping, which then calls the 'myview' view function, which finally renders the 'mypage' template...
index.html
<form method="get" action="{% url 'myview' %}">
urls.py
urlpatterns = patterns('',
url(r'^mypage/$', views.myview, name='myview'),
)
views.py
def myview(request):
return render(request, 'myapp/mypage.html')
However, do I really have to have a url mapping for this? What if I do not want to reload another webpage, and I just want to stay in the same 'index.html' page?
I'm just a little confused over how views are actually called, in the case when I want the view to act more like a traditional function, to process some data, rather than to necessarily render a new template.
Thank you!
You always need a URL if you want your browser to call a view. How else would the server know which view to call? The only way is through the URL mapping. Remember that there is no persistent relationship between the browser and the server: the only way they can communicate is through requests to URLs.
You don't always need to render a template, though. A view can return anything, including raw text or JSON.
I don't understand what you mean about not reloading another page. Posting data to the server is a request for another page: that's just how HTTP works. You can certainly choose to post to the same page you're currently on; and in fact that's exactly how forms are processed in the recommended Django pattern. But you still need a URL mapping pointing at that page, in order to get it in the first place as well as to process the submitted dat.
Besides understanding and accepting Daniel Roseman's answer you could also look at these two packages:
Django Rest Franework
jQuery Form Plugin

Django path not resetting after use of form

On a page called games/vote I have a form that uses the path "add_title/" as its action:
<form method="post" action="add_title/" method="post">
I return the following from the associated view:
return render_to_response('games/votes.html', {'vote_list': not_owned_vote_list,},
context_instance = RequestContext(request))
The url then remains at games/vote/add_title upon return from the view.
I tried changing the path and path_info attributes of the request but to no avail:
request.path = "/games/vote/"
request.path_info = "/games/vote/"
I want the path to be /games/vote upon return to the web page.
What am I doing wrong?
You can't change the path like that. The only way to do it is to tell the browser to redirect to a different URL - which, in fact, is exactly the thing you are recommended to do by the docs after a form POST.
if form.is_valid():
... process ...
return HttpResponseRedirect('/games/vote/')
(Also you should look at using named URLs and reverse() rather than hard-coding the URLs.)