Deleting rows from database with python flask? - python

I am using a flask framework, and can't seem to delete rows from the database. The code below gives a 405 error: "The method is not allowed for the requested URL." Any ideas?
In the py:
#app.route('/delete/<postID>', methods=['POST'])
def delete_entry():
if not session.get('logged_in'):
abort(401)
g.db.execute('delete from entries WHERE id = ?', [postID])
flash('Entry was deleted')
return redirect(url_for('show_entries', post=post))
In the html:
<h3>delete</h3>

Clicking <a href...>delete</a> will issue a GET request, and your delete_entry method only responds to POST.
You need to either 1. replace the link with a form & submit button or 2. have the link submit a hidden form with JavaScript.
Here's how to do 1:
<form action="/delete/{{ entry.id }}" method="post">
<input type="submit" value="Delete />
</form>
Here's how to do 2 (with jQuery):
$(document).ready(function() {
$("a.delete").click(function() {
var form = $('<form action="/delete/' + this.dataset.id + '" method="post"></form>');
form.submit();
});
});
...
Delete
One thing you should not do is make your delete_entry method respond to GET. GETs are meant to be idempotent (are safe to run repeatedly and don't perform destructive actions). Here's a question with some more details.

Alternatively, change POST to DELETE to get you going.
#app.route('/delete/<postID>', methods=['DELETE'])
Ideally, you should use HTTP DELETE method.

I used flaskr as a base for my Flask project (as it looks like you did as well).
In the .py:
#app.route('/delete', methods=['POST'])
def delete_entry():
if not session.get('logged_in'):
abort(401)
g.db.execute('delete from entries where id = ?', [request.form['entry_id']])
g.db.commit()
flash('Entry deleted')
return redirect(url_for('show_entries'))
In the HTML:
<form action="{{ url_for('delete_entry') }}" method=post class=delete-entry>
<input type="hidden" name="entry_id" value="{{ entry.id }}">
<input type="submit" value="Delete" />
</form>
I wanted a button, but you could easily use a link with the solution here.

A simple <a href= link in HTML submits a GET request, but your route allows only PUT requests.
<a> does not support PUT requests.
You have to submit the request with a form and/or with JavaScript code.
(See Make a link use POST instead of GET.)

Related

HTML name/value button attribute not being sent via POST request to server

I am currently using HTMX and Django to process button clicks within a table that adds the selected item to a list. I am trying to use the name/value HTML attributes to send to the backend with the value being dynamic based on the database information. I have the following form code:
<form action="" method="post">
{% csrf_token %}
<button hx-post="{% url 'add-analysis' %}" hx-target="#analysis-list" type="submit" name="projectChoice" value="{{project.project_title}}">Add</button>
</form>
in my Views.py I am trying to parse the data with the following code:
def add_analysis(request):
proj_name = request.POST.get("projectChoice")
print(list(request.POST.items()))
print(request.data())
return render(request, 'includes/analysis-list.html', {"selected_projects" : proj_name})
This returns None however. To debug this I tried listing all of the POST requests to the server with the following:
print(list(request.POST.items()))
However this only returns the CSRF token, what am I doing wrong here?
htmx sends the button value with the posted data when the request attribute hx-post is placed on the form itself.
<form hx-post="/form" hx-target="#result">
<button name="submit1" value="foo" type="submit">Submit 1 (foo)</button>
<button name="submit2" value="bar" type="submit">Submit 2 (bar)</button>
</form>
Here's a live example https://codepen.io/jreviews/pen/PoEJYMX
In your case you can try to do something different on the server side depending on the button that was used to submit the form.

Redirect function not working in Python Flask

I'm sure this has a very simple solution, I have just not managed to find one anywhere on the web (that works in my case). I am trying to build a simple web app and I would like to redirect the user to a predefined #app.route() at the click of a button. I can do it indirectly by displaying a hyperlink, but would obviously much prefer if the redirection was automatic.
This is my 'Home page' >>
#app.route("/", methods=["GET", "POST", "PUT"])
def f_page():
if request.method == "POST":
# print(request.form["action"])
if request.form["action"] == "Officers":
# print(request.form["action"])
return redirect("/in2")
if request.form["action"] == "Companies":
return redirect("/in3")
return '''
<html>
<body>
<p>What do you wish to seed the network with?</p>
<form method="post" action="/">
<p><input type="submit" name="action" value="Officers" /></p>
<p><input type="submit" name="action" value="Companies" /></p>
</form>
</body>
</html>
'''
Note : The commented out 'print(request.form["action"])' was simply included to verify that my code was in fact reaching that point (which it was)
And my '/in2' & '/in3' function is >>
#app.route("/in2", methods=["GET", "POST", "PUT"])
def in2():
return("Hello")
#app.route("/in3", methods=["GET", "POST", "PUT"])
def in3():
return("Hello")
After clicking either button I would expect to see a page load with the words 'Hello', but instead my homepage is loaded and '27.0.0.1 - - [27/Jul/2021 15:47:33] "POST / HTTP/1.1" 302 -' is displayed in my terminal.
I am aware I can change the page that gets loaded by altering the route in the form action '<form method="post" action="/">' but this complicates things further down the line. I was hoping to find a solution using a similar method to that detailed above.
Any help is much appreciated!!!

Django: call method after clicking button

I was searching for this answer but none met my expectation. So, In my template I have some content and wanted to add button (which later will add to favorites). After clicking I want to call method from my views.py and redirect to other view.
my views.py
def home(request):
//logic here
request.session['url'] = url
return render(request,'file.html')
def function_to_call(request):
///logic here
url = request.session.get('url')
return render(request,'second_file.html',url=url)
file.html
<form action="{% url 'function_to_call' %}">
<button id="submit" type="button" value="Click" />
</form>
and in my urls.py
url(r'^function_to_call/',views.function_to_call,name='function_to_call'),
Unfortunately, after clicking on button, nothing happens
unless you are submitting a form, you should use
Click
If for some reason you need to use a POST request rather than a GET this will work:
<form method="POST" action="{% url 'function_to_call' %}">
<button id="submit" type="submit" value="Click" />
</form>
Using a post can be helpful when you don't want to include data in the querystring because it's a little less secure than having the parameters in the request's body.

Flask - 400 Bad request

I have this python code which should take in data from an html form and use it in a WHERE clause:
#app.route('/search', methods=['GET'])
def search():
connect = cx_Oracle.connect("benjamin", "siliyetu", "PRINCE-PC/XE")
cursor = connect.cursor()
searched = request.form['search']
named_params = {'search':searched}
query = cursor.execute("SELECT * FROM edited WHERE REGEXP_LIKE (cod_ed,
:search) OR REGEXP_LIKE (nome_ed,:search) OR
REGEXP_LIKE (endereco,:search) OR REGEXP_LIKE
(telefone,:search) OR REGEXP_LIKE
(cidade,:search)", named_params)
results = cursor.fetchall()
posts = list(results)
return render_template('search.html', posts=posts)
and the template I'm using is this(part of the template anyway. Its not the whole thing):
<form method="POST" action="/editora" class="form-outline" >
<div class="col-lg-7 col-offset-6 right">
<div class="form-group mx-lg-3 mb-2">
<label for="element-7" ></label>
<input id="search" name="search" type="text" class="form-control" placeholder="Pesquisar..." />
<label></label>
<a class="btn btn-primary " type="submit" href="search">Pesquisa</a>
When I try to use the data from the form, it gives me a
werkzeug.exceptions.HTTPException.wrap.<locals>.newcls: 400 Bad Request: KeyError: 'search'
But when I input data using input() it works fine. What gives!?
How would I go about fixing this issue? I also want to add some regular expressions in the where clause but its not budging. How do I do that too?
Ps- I'm working with oracle express edition 11g
Without having a traceback (you are running with the debug server while developing, right?), the exception you're getting comes from the
searched = request.form['search']
line.
the HTML example you have POSTs to /editora
the Python code you have has a route /search (not /editora) and the view won't accept POST requests anyway (methods=['GET']).
Are you sure the snippets you've posted are correct?
request.form is only populated for POST requests, anyway.
If you want to submit data to search route, you form action should point to that route.
<form method="POST" action="/search" class="form-outline" >
And if you want for a search route to get that data from POST request, you should put in methods 'POST' value.
#app.route('/search', methods=['GET', 'POST'])
The reason why you get:
werkzeug.exceptions.HTTPException.wrap.<locals>.newcls: 400 Bad Request: KeyError: 'search'
because you are sending something to the application or server that they cannot handle. (http://werkzeug.pocoo.org/docs/0.14/exceptions/#werkzeug.exceptions.BadRequest)
KeyError is for trying to access dict object parameter 'search' which doesn't exist beucase form is never submited.

Pyramid app: How can I pass values into my request.route_url?

I have this in my views.py file as the view config for my home page:
#view_config(route_name='home_page', renderer='templates/edit.pt')
def home_page(request):
if 'form.submitted' in request.params:
name= request.params['name']
body = request.params['body']
page=Page(name,body)
DBSession.add(page)
return HTTPFound(location=request.route_url('view_page',pagename=name))
return {}
Also, here is the form in the edit.pt template:
<form action="/view_page" method="post">
<div>
<input type="text" name="name"/>
</div>
<div>
<input type="text" name="body"/>
</div>
<label for="stl">Stl</label>
<input name="stl" type="file" value="" />
<input type="submit" name='form.submitted' value="Save"/>
</form>
Also in my init.py file I have
config.add_route('home_page', '/')
config.add_route('view_page', '/{pagename}')
right now when I submit the form it just tries to go to localhost:6543/view_page. This returns a 404 as there is no view_page resource or route leading to it. Instead I want it to go to localhost:6543/(the name of the page I just created aka the first input box in the form). How can I do this?
Edit: I am worried that something else may be telling it to route to view_page because I even tried changing it to
return HTTPFound(location=request.route_url('front_page',pagename=name))
And it still goes to /view_page. There is no route named front_page, so I would at least suspect it to throw an error.
Also, I would really appreciate it if you could tell me where you found the info. I have been looking at http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/api/request.html?highlight=request.route_url#pyramid.request.Request.route_url but can't seem to find use from it.
Edit: should I be using an asset specification instead of a path name? so
return HTTPFound(Location=request.route_url('tutorial:templates/view.pt','/{pagename}'))
Also, I am working through this article which seems very helpful with the syntax: http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#urldispatch-chapter
I think your form should submit to "/", ie.
<!-- where your home_page route is waiting for the POST -->
<form action="/" method="post">
With the prior answers this now looks correct:
return HTTPFound(location=request.route_url('view_page', pagename=name))
My first guess is that it's location not Location as the argument to HTTPFound.
from the link you give
it's should be
return HTTPFound(location=request.route_url('view_page',pagename=name))
when you had add this route
config.add_route('view_page', '/{pagename}')
and set the variable name before
name= request.params['name']

Categories

Resources