Why request.method is not getting invoked? - python

I have a read-only textbox which preloaded value from database which upon a button click sends it's value to a method present in backend to perform DELETE query of sql. The problem is occuring when I am click on the button the method is invoked but the request.method condition is not invoked. It is directly going to the end return statement of the method.
#app.route('/home/delete_reminder/<string:id_val>',methods=['GET','POST'])
#is_logged_in
def delete_reminder(id_val):
if request.method=='POST':
desc = request.form['description']
x = desc.split(',')
cur = mysql.connection.cursor()
cur.execute('DELETE FROM set_reminder WHERE DATE=%s,SUBJECT=%s,DESCRIPTION=%s',[x[0],x[1],x[2]])
cur.execute('DELETE FROM recur WHERE RECUR_NEXT=%s',[id_val])
flash('Reminder Deleted','danger')
mysql.connection.commit()
cur.close()
return redirect(url_for('search_reminder_to_delete'))
This is my backend code.
<form method="POST">
{% for data in value %}
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
Delete Reminder
{% endfor %}
</form>
This is the html part.

Your button isn't a button, it's a link. You aren't submitting your form.
If you want to fo that then you need to make you form tag:
<form method="POST" action="/home/delete_reminder/{{data.RECUR_NEXT}}">
and switch your button to be a real button that submits the form:
<div class="button">
<button type="submit" class="btn btn-warning">Send your message</button>
</div>
EDIT: Seeing that you want to have multiple possible routes for your form based on the loop.
You could try and use the formaction attribute, although it isn't going to be supported by every browser version.
<form method="POST">
{% for data in value %}
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
<div class="button">
<button formaction="/home/delete_reminder/{{data.RECUR_NEXT}}" class="btn btn-warning" type="submit" class="btn btn-warning">Delete Reminder</button>
</div>
{% endfor %}
However this will still result in your description field that is passed to the request having every single description from the whole form in a list or possibly just the last one as a single value (I can't quite remember the behaviour of multiple inputs with the same name), which I don't think is what you're expecting to happen.
It may just be easiest to create a separate form for each link in a loop to be honest:
{% for data in value %}
<form method="POST" action="/home/delete_reminder/{{data.RECUR_NEXT}}">
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
<div class="button">
<button class="btn btn-warning" type="submit" class="btn btn-warning">Delete Reminder</button>
</div>
</form>
{% endfor %}

Related

Django multiple radio input from HTML form with same name

I am having a problem with Django forms. I am currently using the request.POST to validate the POST within views.
I want to send inputed-data(radio type) from my template with the same name.
In my template.py:
<form method="post" action="{% url 'app:AnsSubmission' %}">
{% csrf_token %}
{% for i in Exam %}
<div class="form-group col-xl-12">
<label>{{ i.question }}</label>
<div class="radio">
<label><input type="radio" class="mx-2" name="givenAns" array_column="{{ i.pk }} value="True" required>True</label>
</div>
<div class="radio">
<label><input type="radio" class="mx-2" name="givenAns" array_column="{{ i.pk }} value="False" required>False</label>
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
And willing to fetch these data in views.py like:
givenAns_list = request.POST.getlist('givenAns')
for i in givenAns_list:
this_givenAns = givenAns_list[i]
But the problem here is this radio type input field doesn't take value for the same name(not as a list I wish). If I select answer of 2nd question, the 1st one's selection is unselected.
Please suggest how can I fix this?

Can't access an item in a dictionary that does in fact exist

I have two buttons on my page, each one in its own separate form.
One of the buttons, "deleteImage", works perfectly fine.
The other button, "search", won't work.
This is my response.POST when search is pressed.
request.POST <QueryDict: {'csrfmiddlewaretoken': ['randomtoken1234'], 'search': ['food', '']}>
request.POST.get("search") is failing to work for some reason, I tried printing it as well and nothing prints out.
my html
<form method="post" action="" class="form-group">
{% csrf_token %}
<div class="input-group mb-3">
{{form_search.search}}
<div class="input-group-append">
<button type="submit" class="btn btn-primary" name="search">Search!</button>
</div>
</div>
Looking at the QueryDict the key search is shown as 'search': ['food', '']. This means there are two values posted for search where one is an empty string.
I assume that this is because other than your button the form field for the search input is also named search. When one writes request.POST.get("search") they get the last value for the given key which here is an empty string for you (the value of the button).
The solutions are:
Change the name of the form field from search to something else.
Change the name of the submit button from search to something else. Which will be something like:
<form method="post" action="" class="form-group">
{% csrf_token %}
<div class="input-group mb-3">
{{form_search.search}}
<div class="input-group-append">
<!-- Change name attribute of button -->
<button type="submit" class="btn btn-primary" name="search-pressed">Search!</button>
</div>
</div>
</form>
Note that you might need to make some changes in your view as well to reflect these changes in the name.
Fixed by adding a value to the search button
<form method="post" action="" class="form-group">
{% csrf_token %}
<div class="input-group mb-3">
{{form_search.search}}
<div class="input-group-append">
<button type="submit" class="btn btn-primary" name="search" value="{{form_search.search}}">Search!</button>
</div>
</div>
</form>

Contained submit button validating other forms

I have two forms on my page, each with its own fields and submit button, but whenever I use any of them, they always check the overall page fields instead of just the form they're contained in...
The simulator.html has two forms, the first one is this:
<div class="forms">
<div class="form-1">
<form method="post" action="{{ url_for('core.simulator') }}">
<div class="container">
<div class="row g-3">
<div class="col-sm-3">
<label class="form-label"><b>Capital:</b></label>
<input type="text" class="form-control" name="capital_html" required>
</div>
<div class="col-sm-3">
<label class="form-label"><b>Price:</b></label>
<input type="text" class="form-control" name="price_html" required>
</div>
</div>
</div>
<br>
<div class="d-grid gap-2 d-md-flex justify-content-md-start">
<button id="btn" type="submit" class="btn btn-info">Launch simulation!</button>
</div>
</form>
<br>
<p>Units to purchase: <b>{{simulation_units}}</b>
</div>
</div>
And the second one is this:
<h3> Screener</h3>
<div class="forms">
<div class="form-2">
<form method="post" action="{{ url_for('core.simulator') }}">
<div class="container">
<div class="row g-3">
<div class="col-sm-3">
<label class="form-label"><b>Ticker:</b></label>
<input type="text" class="form-control" name="ticker_symbol_html" placeholder="Enter Ticker Symbol" required>
</div>
</div>
</div>
<br>
<div class="d-grid gap-2 d-md-flex justify-content-md-start">
<button id="btn" type="submit" class="btn btn-info">Launch!</button>
</div>
<p>Symbol <b>{{simulation_symbol}}.
</form>
</div>
</div>
The views.py file has the back-end code for each, the first one is this:
def capital_simulator():
if request.method == 'POST':
simulation_capital = request.form.get('capital_html', '')
simulation_price = request.form.get('price_html', '')
try:
simulation_units = math.floor(float(simulation_capital) / float(simulation_price))
except KeyError:
simulation_units == 0
return render_template('simulator.html',form1=form,capital_html=simulation_capital,price_html=simulation_price,simulation_units=simulation_units)
And the second form back-end script is this:
def screener():
if request.method == 'POST':
ticker_symbol = request.form.get('ticker_symbol_html', '')
return render_template('simulator.html',ticker_symbol=ticker_symbol_html,ticker_symbol=simulation_symbol)
I thought by specifically calling the mentioned fields and containing them into forms classes, I would avoid an overall validation, but right now I'm failing to make the submit button focus on their own forms. How can I fix this, please?
You have two forms. One is within the 'form-1' div. One is within the 'form-2' div. Each one has its own <form> and </form> tags, which means they are separate forms. The first form contains two <input> fields: one called capital_html, one called price_html, and a button called btn. The second form has one <input> field called ticker_symbol_html and a button called btn.
Let's say the user fills in the first two fields and clicks the first button. That's going to send a request to whatever the URL is in the <form> tag. In the data, it will send three things:
capital_html=xxx
price_html=yyy
btn=submit
That's it. That's all you get. You don't get any fields from the other form. If the user clicks the other form, all you will get is
ticker_symbol_html=xxx
btn=submit
The problem, as you can see, is there's no easy way for you to tell which form was submitted. If you have to use the same URL for both, the usual way to solve this is to add a hidden field that gets sent with the data, like:
<input type=hidden name="ident" text="form1">
and in the second one:
<input type=hidden name="ident" text="form2">
Now, your handler can say
if request.form.get("ident") == "form1":
# Go handle first form.
else:
# Go handle second form.

Add a hidden field with an object value in Django/Python

I am trying to create an app where a user can manage a database of "Lost property" items. To do so I have a main page where all the items are displayed and I have a button per row to be clicked when the item is returned to the owner.
That button is submitting a form that should contain the ID value of the element that has been clicked so I trying to get something like
<input id="id_id" name="id" type="hidden" value="{{lostitem.id}}">
But I don't know how to pass that value to my form ! Here is my template :
{% for lostitem in lostitems %}
<tr>
<td>{{lostitem.id}}</td>
<td>{{lostitem.description}}</td>
<td>
<form class="give-back-item-form" method="POST">
{% csrf_token %}
{{formGiveBackItem.as_p}}
<button type="submit" class="button btn btn-xs btn-success buttonItems">
<span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span>
</button>
<!-- TRYING TO ADD A HIDDEN INPUT WITH THE ID AS VALUE -->
</form>
</td>
</tr>
{% endfor %}
Here is my form from forms.py
class GiveBackItemForm(forms.ModelForm):
id = forms.CharField(widget=forms.HiddenInput())
class Meta:
model = ItemLost
fields = ('id',)
And here is where I'm trying to get my $_POST['id'] and to update my object (I couldn't test this part as I'm not getting any POST information at the moment) :
from .forms import GiveBackItemForm
"""Defining our views"""
def item_list(request):
formGiveBackItem = GiveBackItemForm()
"""Ordering objects by date of creation"""
lostitems = ItemLost.objects.filter(added_date__lte=timezone.now()).order_by('added_date')
if request.method == "POST":
"""Giving back an item"""
itemToGive = ItemLost.objects.get(pk=request.POST.get('id'))
itemToGive.giveBackItem
"""Returning our ordered objects to the view"""
"""Request = everything we receive from the user (in a form for example)"""
return render(request, 'lostitem/item_list.html', {'lostitems': lostitems, 'formGiveBackItem' : formGiveBackItem})
Thanks for any help or remark about the code ! I'm just getting started and it was really hard to find anything helpful about my problem
EDIT : I managed to make it work by still using the Django ModelForm and the view to handle my form
Here is my code in my view :
def item_list(request):
"""Ordering objects by date of creation"""
lostitems = ItemLost.objects.filter(added_date__lte=timezone.now()).order_by('added_date')
"""To get data from the form"""
give_back_item_form = GiveBackItemForm(request.POST or None)
# check if form is valid
if give_back_item_form.is_valid():
itemToGive = ItemLost.objects.get(pk=give_back_item_form.cleaned_data['id'])
itemToGive.returned_date=timezone.now()
itemToGive.save()
# your rest of the code here
"""Returning our ordered objects to the view"""
"""Request = everything we receive from the user (in a form for example)"""
return render(request, 'lostitem/item_list.html', {'lostitems': lostitems, 'give_back_item_form' : give_back_item_form})
And here is the code for my template !
<form class="give-back-item-form" method="POST">
{% csrf_token %}
<input type="hidden" name="id" value="{{ lostitem.id }}">
<button type="submit" class="button btn btn-xs btn-success buttonItems">
<span class="glyphicon glyphicon-share-alt" aria-hidden="true"> </span>
</button>
</form>
Thank you all for your answers it lead me to the right solution !
If all you want to do is post back the id of an associated ItemLost object so that you can invoke a method on it (e.g., giveBackItem()), there's no need to use a ModelForm at all. Just use a normal HTML <form>, and manually put the hidden field in it:
<form class="give-back-item-form" method="POST">
{% csrf_token %}
<button type="submit" value="Give Back">
<input type="hidden" name="id" value="{{lostitem.id}}">
</form>
So your complete template would become:
{% for lostitem in lostitems %}
<tr>
<td>{{lostitem.id}}</td>
<td>{{lostitem.description}}</td>
<td>
<form class="give-back-item-form" method="POST">
{% csrf_token %}
<button type="submit" class="button btn btn-xs btn-success buttonItems">
<span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span>
</button>
<input type="hidden" name="id" value="{{lostitem.id}}">
</form>
</td>
</tr>
{% endfor %}

How to get the data from HTML field to the view.py in django(HTML field is iterating)

I have an app which reads the questions from database and display them .I need to enter the response to it and save it back in the database.Is it possible to do it without using forms
My HTML section
<form id="survey" method="post" action="/Survey/restricted/" class="form col-md-12 center-block">
{% csrf_token %}
{% for b in obj1 %}
<textarea class="form-control">{{b.question}}</textarea>
<textarea class="form-control" rows="3" name="response1" width="100%;">{{b.response}}</textarea>
{% endfor %}
<input type="submit" name="submit" class="btn btn-success" value="Submit Response" />
</form>
I tried to access the data after entering the response and submitting using
res=request.POST.get('response1')
but it returns none
You should move the response1 field outside the loop, but then it should be passed as a separate field (e.g. response), not as part of the obj1 list of questions (or not passed at all if keeping the previous answer is unnecessary).
<form id="survey" method="post" action="/Survey/restricted/" class="form col-md-12 center-block">
{% csrf_token %}
{% for b in obj1 %}
<textarea class="form-control">{{b.question}}</textarea>
{% endfor %}
<textarea class="form-control" rows="3" name="response1" width="100%;">{{response}}</textarea>
<input type="submit" name="submit" class="btn btn-success" value="Submit Response" />
</form>
Also, I think the questions should not be editable (i.e. disabled, or not a textarea altogether)

Categories