How can I access the form submit button value in Django? - python

I have a Django project that, on one page, has multiple forms (in different tags) that can be submitted to have different effects. In all cases I want the user to be redirected back to the same page, so I use in my view the pattern of submitting the form and then redirecting to the original page. In at least one case, the only difference between two of the forms is the value of the submit button.
In my view I have the code (which is the first time my view function accesses the request.POST):
if request.POST['submit']=='Add':
#code to deal with the "Add" form
and in the template, the first form has a submit button like
<input type="submit" value="Add">
I thought this would work, but when I submit that form, I get an error at the line in view from above:
Key 'submit' not found in <QueryDict: {u'clientyear': [u'2012'], u'csrfmiddlewaretoken': [u'be1f2f051f09f6ab0375fdf76cf6a4d7'], u'ben': [u'123405']}>
Obviously, this does not have a 'submit' key or any key with the value corresponding to the submit button I clicked. So, since this does not work, how can access the value of the submit button or tell which of the forms has been submitted?

Submit is an HTML Form structure... You must use name attribute of form objects as follows... In your template:
<form>
...
<input type="submit" name="list" value="List Objects" />
</form>
<form>
...
<input type="submit" name="do-something-else" value="Do Something Else" />
</form>
In your view:
if 'list' in request.POST:
# do some listing...
elif 'do-something-else' in request.POST:
# do something else

One thing to keep in mind to prevent confusion. The name of the submit button will not show if there is only a single button in the form.
#template.html
<form action="..." method="post">
<input type="submit" name = "first_button" value="Add">
</form>
#view.py
...
'first_button' in request.POST #False
#template.html
<form action="..." method="post">
<input type="submit" name = "first_button" value="Add">
<input type="submit" name = "second_button" value="Remove">
</form>
#view.py
...
'first_button' in request.POST #True if you clicked on that button

I'm little bit late but here is the solution
Problem you are facing
Your are trying to get Button name but getting the initial value of button that is not correct way.
HTML Code
<input type="submit" value="Add">
Python Code/View.py
if request.POST['submit']=='Add':
#code to deal with the "Add" form
Solution
First find button name in request.POST dictionary if exist then get their value.
HTML Code
Add name of your button and their value.
<input type="submit" value="Add" name="add_object">
Views.py
You can find the button name in request.POST dictionary
if request.POST['submit'] == 'add_object':
# Both ways to deal with it
if 'add_object' in request.POST:
Extra Stuff
We have two forms on a page.
First form have 2 buttons with same name subjects but different values fav_HTML and fav_CSS.
Second form also have 2 buttons with same name tutorials but different values
Tutorials_HTML and Tutorials_CSS.
<form action="" method="post">
Form 1
<button name="subject" type="submit" value="interview_HTML">HTML</button>
<button name="subject" type="submit" value="interview_CSS">CSS</button>
</form>
<form action="" method="post">
Form 2
<button name="tutorials" type="submit" value="Tutorials_HTML">HTML</button>
<button name="tutorials" type="submit" value="Tutorials_CSS">CSS</button>
</form>
views.py
We can handle different forms, check which button is clicked then getting their values and do something.
if 'subject' in request.POST: # this section handle subject form (1st Form)
#now we can check which button is clicked
# Form 1 is submitted , button value is subject now getting their value
if 'interview_HTML' == request.POST.get('subject'):
pass
# do something with interview_HTML button is clicked
elif 'interview_CSS' == request.POST.get('subject'):
pass
# do something with interview_CSS button is clicked
elif 'tutorials' in request.POST: #this section handle tutorials form (2nd form)
#now we can check which button is clicked
# Form 1 is submitted , button name is tutorials now getting their value
if 'Tutorials_HTML' == request.POST.get('tutorials'):
pass
# do something with fav_HTML button is clicked
elif 'Tutorials_CSS' == request.POST.get('tutorials'):
pass
# do something with fav_CSS button is clicked

Related

Avoid changing the address while send GET request (django)

I have url http://127.0.0.1:8000/profile/question/1/ and on the address i have form
i want to have like or dislike button on post. everything work fine but url change is the problem.
it's my code- >
def get_context_data(self, *args, **kwargs):
self.object=self.get_object()
context = super(QuestionDetail, self).get_context_data(**kwargs)
if "like" or "dislike" in self.request.GET:
if "like" in self.request.GET:
if bool(Like.objects.filter(user=self.request.user, question=self.get_object())) == True:
pass
else:
Like.objects.create(user=self.request.user, question=self.get_object())
elif "dislike" in self.request.GET:
if bool(DisLike.objects.create(user=self.request.user, question=self.get_object())) == True:
pass
else:
DisLike.objects.create(user=self.request.user, question=self.get_object())
try:
question = Question.objects.get(id=self.kwargs["pk"])
context['detail'] = question
except ObjectDoesNotExist:
return reverse("Profile:error")
<form class="float-right block">
<button type="submit" name="like" class="block mb-2"></button>
<button type="submit" name="dislike" class="block"></button>
</form>
when i click for example like button, url changed and it's http://127.0.0.1:8000/profile/question/1/?like=
how to avoid this problem? and what is the problem?
thank you
This is correct. When you have multiple submit buttons, on your backend you should have a way to know which submit button was selected. You should have a name and values for each button separately. For example:
<form class="float-right block">
<button type="submit" name="type" value="like" class="block mb-2"></button>
<button type="submit" name="type" value="dislike" class="block"></button>
</form>
The like button will submit the form to:
http://127.0.0.1:8000/profile/question/1/?type=like
And dislike button will submit the form to:
http://127.0.0.1:8000/profile/question/1/?type=dislike
And then in your backend, you can get the type of that to submit button using:
btype = request.GET.get('type', 'like')
# Or if the method of the form is POST use
btype = request.POST.get('type', 'like')

Is there a way to extract data from django templates except the POST method

In one of the pages of my website i m trying to create two buttons save and delete. Save as the name suggests saves the data filled into form in my database. Delete deletes this data. I want to access these two buttons separately in my views.py file but the only way i know to detect user input is checking if request.method == 'POST'. But in the case of both the save and delete button POST request is going to be made. How can i differentiate between the click of delete and save button so that i can write different code for each?
Use the name tag in the button to differentiate between POST operations.
For example:
<button name="delete">Delete</button>
And use in condition in view:
if "delete" in request.POST:
Use two separated form, and submit them by ajax seems the easiest way.
view.py
Create 2 views. One for add/update data, and second one for delete data.
def submit_view(...):
if request.POST:
# add data (if form.is_valid, and more)
def delete_view(...):
if request.POST:
# delete data (if form.is_valid, and more)
template
Now add two separated forms in template, and submit them by using ajax.
<form action="/submit" id="submit_form">
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="button" value="submit" id="submit_button">
</form>
<form action="/delete" id="delete_form">
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="button" value="delete" id="delete_button">
</form>
<script>
$('#submit_button').on('click',function(){$('#submit_form').submit();});
$('#delete_button').on('click',function(){$('#delete_form').submit();});
</script>

How to utilize bootstrap toggle with flask

This question is an extension of this question regarding using the Bootstrap toggle with flask.
My code for the toggle is as follows:
<div class='media'>
<div class='media-left'>
<div class='media-object'>
<div class='padding-right'>
<form action="/menu" method="post">
<input name="toggle" onclick="this.form.submit()" data-off="<i class='fa fa-times'></i> " data-on="<i class='fa fa-check'></i> " data-onstyle='success' data-size='large' data-style='ios' data-toggle='toggle' id='activate-toggle' type='checkbox' value="on">
<input name="toggle" type="hidden" value="off">
</form>
</div>
</div>
</div>
<div class='media-body'>
<div id='console-event'></div>
</div>
</div>
And my endpoint for the page is as follows:
#app.route('/menu', methods=['POST', 'GET'])
def get_callback():
if request.method == 'POST':
button = request.form['toggle']
print(button)
return render_template('dashboard.html')
However I am not able to get any response from my button.
I am very lost at this point. I have tried to copy the format of the question above however I still cannot get the button to print or even use the POST method.
Here are my questions:
How can I get a response from my button?
How do I save the orientation so that when the user logs back in the button is how they previously left it?
(I am using SQLAlchemy if this is of any importance.)
Any help would be greatly appreciated!
Thank you,
Jonah
It seems that the target of your form defined in action is incorrect. What I would try and do is change it to the following:
<form action="{{url_for('get_callback')}}" method="POST">
As for saving the toggled state, you might want to create a column in your db table with a default of off (or on) and then write some code to update the saved value for the switch state whenever a change is made to the toggle switch.
If anyone else has a better idea to store the state of the switch, I'd be interested to find out how.
First of all, you don't need this second hidden input. It's resulting in there being two values for toggle, which isn't what you want.
<input name="toggle" onclick="this.form.submit()" data-off="<i class='fa fa-times'></i> " data-on="<i class='fa fa-check'></i> " data-onstyle='success' data-size='large' data-style='ios' data-toggle='toggle' id='activate-toggle' type='checkbox' value="on">
<input name="toggle" type="hidden" value="off">
But more importantly, your code, as written would print to the console the value of button, then return to the user the HTML form input. Perhaps this would clear things up:
#app.route('/menu', methods=['POST', 'GET'])
def get_callback():
if flask.request.method == 'POST':
button = bool(flask.request.form.get('toggle', False))
return "Toggle value: %r" % (button,)
else:
return render_template('dashboard.html')
If you do that, and remove that hidden input that shouldn't be there, it'll show the user "Toggle value: True" or "Toggle value: False" depending on which is clicked.
Though I don't see, in your example, how the user could submit the form without toggling the checkbox.
i would try it like that
#app.route('/menu', methods=['GET','POST'])
def get_callback():
if request.method == 'POST':
print(request.form.get('toggle'))
return render_template('dashboard.html')
if it does not work with ('toggle') try ('checkbox')

Django - How to create a simple confirmation view?

I'm trying to create a View in which the user is asked to confirm an action of updating a value of an instance. I want the View to only have a submit button. What I want is similar to a DeleteView except what I want is to update a value of a record instead of deleting the record.
I have tried using Class based UpdateView, but it requires that I specify a fields parameter in which I must specify at least one field and I do not want to show any field, just the submit button.
This is what my template now looks like:
<h4>Complete {{ item.name }}?</h4>
<form method='POST' class="gia-form">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="button" value="Complete Item">
Cancel
</form>
Url for the view:
url(r'^action/complete-item/(?P<pk>\d+)/$', views.CompleteItemView.as_view(), name='complete'),
My UpdateView:
class CompleteItemView(UpdateView):
model = models.Item
template_name = 'items/complete_item.html'
fields = ("status",)
def form_valid(self, form):
form.instance.status = 'completed'
return super().form_valid(form)
Above I have chosen to show the status field, and this is what I'm trying to get rid of in an elegant way as I just want to show the confirm button without any fields.
Instead of
{{ form.as_p }}
You can simply write
<input name="{{ form.status.html_name }}" id="{{ form.status.id_for_label }}"
value="{{ form.status.value }}" type="hidden">
This will render the status field as hidden and only the Submit button will be visible.
Have you considered using Bootstrap Modals.
You could have a 'Submit' button which wouldn't actually submit the form, but instead it would open the modal where you could have the form submit button.
You would just have to remember to create the modal inside the form tags.
You could use Javascript like this:
<script>
$(document).on('click', '.some_class', function(){
return confirm('Are you sure you want to update this?');
})
</script>
And add class some_class to your button

django form multiple fields dynamically

So I want to create a member form with Education part that will contain 3 elements:
Foreign Key to Academic_Background (which has High School, BC degree, master degree, etc..),
Charfield - Name of school
Charfield - Field of studies
No problem doing one, or two... but how can I make several "Education" fields (by adding a button of "Add another" and using JS&Jquery to display the new Education to the user.
What should I put in my Model, and in my Form? and how will it be saved in the DB?
It seems like something that probably happened to someone before, yet I couldn't find a solution for that...
Please help !
Thanks
i did this without using django forms .. just using html forms to upload multiple as many as user wishes..
this is my template.html file which has normal form without any input file field initially
the js method adds a new input file field to the form when clicked on "add new item" href
<form action="{{request.path}}" method="post" enctype="multipart/form-data" id="upload_form">
{%csrf_token%}
<input type="text" name="name" id="name" value="{{request.POST.name}}" placeholder="Person Name"/>
<input type="text" name="categorie" id="categorie" value="{{request.POST.categorie}}" placeholder="Categorie"/>
<div class="file_inputs" id="file_inputs">
<!-- <-- field where im adding multiple files initially empty -->
</div>
<input type="submit" value="Upload">
</form>
<!-- link to add new file input box when clicked on it -->
<a href="#" onClick="addformelement()" >add new item</a>
<script type="text/javascript">
// method to add an file input box when clicked on add new item link
function addformelement(){
a = document.getElementById('file_inputs')
divx=document.createElement('div')
divx.class='file_inputs'
x=document.createElement('input');
x.type='file';
x.name='docfile';
divx.appendChild(x);
a.appendChild(divx) ;
}
</script>
and in views i did this
if request.method == 'POST':
name_instance = get_name_instance(request)
if(name_instance == -1):
return HttpResponse("Error - Check Server logs")
for f in request.FILES.getlist('docfile'):
# do your logic for each file f
# as f.name to get filename ...
all my fileinputs have the same id as docfile ...
so in my views i called getlist('docfile')
you can do the same with normal data like
request.POST.getlist('idname')

Categories

Resources