I have two completely different forms in one template. How to process them in one view? How can I distinguish which of the forms was submitted? How can I use prefix to acomplish that? Or maybe it's better to write separate views?
regards
chriss
Personally, I'd use one view to handle each form's POST.
On the other hand, you could use a hidden input element that indicate which form was used
<form action="/blog/" method="POST">
{{ blog_form.as_p }}
<input type="hidden" name="form-type" value"blog-form" /> <!-- set type -->
<input type="submit" value="Submit" />
</form>
...
<form action="/blog/" method="POST">
{{ micro_form.as_p }}
<input type="hidden" name="form-type" value"micro-form" /> <!-- set type -->
<input type="submit" value="Submit" />
</form>
With a view like:
def blog(request):
if request.method == 'POST':
if request.POST['form-type'] == u"blog-form": # test the form type
form = BlogForm(request.POST)
...
else:
form = MicroForm(request.POST)
...
return render_to_response('blog.html', {
'blog_form': BlogForm(),
'micro_form': MicroForm(),
})
... but once again, I think one view per form (even if the view only accepts POSTs) is simpler than trying to do the above.
like ayaz said, you should give unique name to form submit button
<form action="." method="post">
......
<input type="submit" name="form1">
</form>
<form action="." method="post">
......
<input type="submit" name="form2">
</form>
#view
if "form1" in request.POST:
...
if "form2" in request.POST:
...
If the two forms are completely different, it will certainly not hurt to have them be handled by two different views. Otherwise, you may use the 'hidden input element' trick zacherates has touched upon. Or, you could always give each submit element a unique name, and differentiate in the view which form was submitted based on that.
Related
i would like to pass a value to a form through a get request. It can be done using wtforms but i'm not using that so i'd to know how to do it with request.form['test'] instead of form.test.data. Below is how it would work with wtform. I'd like to replicate that with a normal form.
if request.method == 'POST':
current_user.firstname= form.firstname.data
elif request.method == 'GET':
form.firstname.data= current_user.firstname
in other words, i'm making a page to update a user's data. I'd like to display what's in the database on the input form. Then when they edit it and hit update, whatever's on the form field will be updated in the DB. I'm not using WTForms. I hope there's a way to do this without it.
The form looks like this
<form method='post' action="/action_page">
First name:<br>
<input type="text" name="firstname" value="Mickey">
<br>
Last name:<br>
<input type="text" name="lastname" value="Mouse">
<br><br>
<input type="submit" value="Submit">
</form>
you can pass values to the form by passing parameters to the render_template method just like this
firstname= " ah"
lastname= " 1233"
return render_template("form.html", name=firstname, last=lastname)
then in HTML you can use jinja to put these values in the form
<form method='post' action="/action_page">
First name:<br>
<input type="text" name="firstname" value={{name}}>
<br>
Last name:<br>
<input type="text" name="lastname" value={{last}}>
<br><br>
<input type="submit" value="Submit">
</form>
How do you pass form inputs to a form action in Django? I tried this but it's not working
<form action="/search?search_term=q" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
I'm assuming you're asking how to link an HTML form to a view function for processing. Note that in Django, we don't call them actions.
Here's the basic form and placeholder for the search results that you'd put in a Django template:
<form action="/search" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
{% if search_results %}
Display search results here.
{% endif %}
If you type apple into the text field and then click the search button on this form it will make a GET request to /search?q=apple.
You will need to route the request via a URLconf to a view function to do the processing.
The entry in the URLconf may look like the following:
from django.conf.urls import url
from app import views
urlpatterns = [
# ...
url(r'^search/$', views.search),
# ...
]
views.search is the view function that does the processing. Here's a possible implementation:
from django.shortcuts import render
def search(request):
q = request.GET.get('q')
if q is None:
return render(request, 'app/search.html')
search_results = perform_search(q)
context = { 'search_results': search_results }
return render(request, 'app/search.html', context)
Where perform_search is a function you'd need to write to do the actual searching.
When you specify a method GET in form, then You don't need to append parameters explicitly in the URL. When the user submits the form your parameter will automatically append in the URL as key-value pairs.
Example
<form action="search" method="GET">
<input type="text" name="search_item1">
<input type="text" name="search_item2">
<input type="submit" value="Search">
</form>
When a user hit submit button then your parameter(serach_item1 and serach_item2) will append implicitly in action URL. where keys are input fields name attribute
Now your URL looks like
www.example.com/search?search_item1=<serach1>&search_item2=<serach2>
To pass GET arguments to the page you don't need to specify it in action attribute.
Just do follow:
<form method="GET" action="search/">
<input type="text" name="search_term" value="{{ request.GET.search_term }}">
<input type="submit" value="Search">
</form>
this will redirect you to the page http://yourdomain.com/search?search_term=search_text.
Please note I replaced input name attribute to rename GET argument to search_term. Also I added value attribute to display current search text to the input field.
shuboy2014 and neverwalkaloner are correct. But a fact they didn't tell you is that you'll pass empty values if you declare no values in that fields. For example:
<form method="GET" action="search/">
<input type="text" name="search_term">
<input type="submit" value="Search">
</form>
That would create an URL like http://yourdomain.com/search?search_term=, which could lead to unexpected errors in the View later. You either should do request.GET.get("search_term") to avoid exceptions or modify the submit function of your form to dinamically remove the names of those empty fields.
There is template:
<form action="{% url 'nfoapp.views.kinoscrap' <I WANT MOVIE_ID THERE> selectshort.id %}" method="post">
<input type="text" class="form-control" name="MOVIE_ID">
<button type="submit" class="btn btn-danger">Kinopoisk Search by ID</button>
</form>
There is my urls.py:
(r'^kinoscrap/(?P<kinoid>\d+)/(?P<shortid>\d+)/$', kinoscrap),
I want pass to kinoscrap two parameters - text field from form (MOVIE_ID) and 'selectshort.id' variable. The problem is that i can't put simple MOVIE_ID in first line of template, I got error. But when I try put instead MOVIE_ID other variable, for example selectshort.id, program work without error.
How I can trasmit text field value to view?
p.s I use bootstrap, if it has some importance.
You could have the form action empty, so to the same view, and then in the view redirect using the POST data from the form.
<form action="" method="post">
<input type="text" class="form-control" name="MOVIE_ID">
<button type="submit" class="btn btn-danger">Kinopoisk Search by ID</button>
</form>
And then in the view
def searchView(request):
if request.method == 'POST':
# get variables from form and redirect
else:
# do your normal rendering
(r'^kinoscrap/(?P<kinoid>\d+)/(?P<shortid>\d+)/$', kinoscrap),
Your urls.py accepts to integer values in the url (something like kinnoscrap/12/21), if you pass anything beside integers it'll throw an error. If you want to pass a text field you'll have to change the regular expression.
Try out your regexes at regex101 here to see if they'll work.
So i've looked around and it seems nobody has had the same problem that I am having to cause this seemingly common error. I am rendering some forms in my html as follows:
<form method="post" action="">
{{ tags_formset.management_form }}
<!-- code displaying this formset -->
...
<!-- -->
<form method="post" action="">
{{ add_all_form.management_form }}
{{ add_all_form.addTagsToAll }}
<input type="submit" value="Add To Displayed Applicants" />
</form>
<form method="post" action="">
{{ remove_all_form.management_form }}
{{ remove_all_form.removeTagsFromAll }}
<input type="submit" value="Remove From Displayed Applicants" />
</form>
<input type="submit" value="Save Changes" />
</form>
When i did not have the two inner forms the formset is displayed correctly and the submit button works to submit the form. When i added the 2nd two forms a couple of problems occured:
-The submit button stopped working (though pressing enter while one of the formset's fields is selected still submits the form
-The add_all_form's submit works and it functions propperly (not a problem but interesting concerning the next point...)
-The remove_all_form does not work ad throughs the 'ManagementForm data is missing or has been tampered with' validation error.
Here is the views.py code that creats the forms:
TagsFormSet = formset_factory(TagsForm, formset=TagFormSet, extra=applicantQuery.count())
if request.method == 'POST':
tags_formset = TagsFormSet(request.POST, request.FILES, prefix='tags', applicants=applicantQuery)
add_all_form = TagAddAllForm(request.POST, request.FILES, prefix='addForm', applicants=applicantQuery)
remove_all_form = TagRemoveAllForm(request.POST, request.FILES, prefix='removeForm', applicants=applicantQuery)
redirect = False
if tags_formset.is_valid():
for tagForm in tags_formset.forms:
if 'tags' in tagForm.cleaned_data:
tagForm.saveTags()
if 'removeTags' in tagForm.cleaned_data:
tagForm.deleteTags()
redirect = True
if add_all_form.is_valid():
if 'addTagsToAll' in add_all_form.cleaned_data:
add_all_form.saveTagsToAll()
redirect = True
if remove_all_form.is_valid():
if 'removeTagsFromAll' in remove_all_form.cleaned_data:
remove_all_form.deleteTagsFromAll()
redirect = True
if redirect:
return http.HttpResponseRedirect('')
else:
initForms = []
tags_formset = TagsFormSet(prefix='tags', applicants=applicantQuery)
add_all_form = TagAddAllForm(prefix='addForm', applicants=applicantQuery)
remove_all_form = TagRemoveAllForm(prefix='removeForm', applicants=applicantQuery)
I literally can not figure out what is going wrong. I don't know why the add_all_form works when the remove_all_form does not, as i basically copy and pasted everything involved (if you need i can post the code from the Forms.py file but I don't think the problem is there...)
Please help!
You should use only one <form> tag. You can have as many submit button as you want here and can display as many forms as you want, but all should be inside a single <form> tag.
Then all the management data will be sent properly in form submit and your issue should be fixed.
<form method="post" action="">
{{ tags_formset.management_form }}
<!-- code displaying this formset -->
...
<!-- -->
{{ add_all_form.management_form }}
{{ add_all_form.addTagsToAll }}
<input type="submit" value="Add To Displayed Applicants" />
>
{{ remove_all_form.management_form }}
{{ remove_all_form.removeTagsFromAll }}
<input type="submit" value="Remove From Displayed Applicants" />
<input type="submit" value="Save Changes" />
Your view can remain as it is.
I have the following code in my template:
<form action="" method="post">{% csrf_token %}
{%for category, category_votes in votes%}
<p>{{category}}: {{category_votes}} <!-- displays as expected -->
<input type="hidden" name="votedCat" value="{{category}}" id={{forloop.counter}}>
<input type="submit" name="upvote" value="Vote for...">
<input type="submit" name="downvote" value="Vote against...">
</p>
{%endfor%}
</form>
The variable {{category}} displays as expected when rendered, but looking in the POST data, "votedCat" is always the last category value in votes.
For example, if votes=[('a',1),('b',2),('c',3)], then request.POST['votedCat'] returns 'c' regardless of which input button is used to submit the form. What did I do wrong?
Because you only have one single form, with multiple inputs for votedCat. Clicking any of the buttons submits the whole form, with all the values for votedCat. If you were to access request.POST.getlist('votedCat') you would see that you actually have all the values.
There are two ways of fixing this. The first is to have separate form elements for each iteration through the loop - to do that, just move the <form> and </form> elements inside the loop.
The second is to have the votedCat input actually be the submit button:
<input type="submit" name="votedCat" value="Vote for {{category}}" id={{forloop.counter}}>
The disadvantage here is that now you have the words 'Vote for' in your variable, which you'll need to parse out in the view code.
Better than both of these would be to have a simple radio button set or select box with a single submit button, but I understand that design requirements sometimes get in the way.
Finally, you should really be using Django's forms framework, rather than using manual HTML and dealing with the POST directly.
I'm not sure if this is the best solution, but you can create a new form inside the loop:
{%for category, category_votes in votes%}
<p>{{category}}: {{category_votes}} <!-- displays as expected -->
<form action="" method="post">{% csrf_token %}
<input type="hidden" name="votedCat" value="{{category}}" id={{forloop.counter}}>
<input type="submit" name="upvote" value="Vote for...">
<input type="submit" name="downvote" value="Vote against...">
</form>
</p>
{%endfor%}
You could consider using the django.forms.Form class to build and process your forms.