How to get an input from textbox using Flask - python

This is my app.route that I'm trying to reach:
#app.route('/advance_search',methods=['GET','POST'])
def advance_search():
word=""
word = request.form['kword']
result=[]
result=getListOfKeyWord(word)
return render_template('advance_search.html',key=result)
This is the HTML I'm trying to reach from the home page (advance_search):
<form action="/advance_search" method="POST" class="col s12">
<div class="row center">
Advanced
</div>
</form>
and this is the HTML of the advance_search.html I'm trying to reach:
<form action='/advance_search' method="POST" enctype="multipart/form-data" >
<div class="row">
<label for="first_name"><b>Keyword</b></label>
<br>
<input id="kword" name='kword'type="text" class="btn" placeholder="type & hit Enter">
</div>
<div class="row center">
<button type="submit" class="btn-large waves-effect waves-light orange">Search</button>
</div>
<div class="row center">
{{key}}
</div>
</form>
When I try to click on the (Advanced) button in order to go to the `advance_search.htmln page I get this error:
**werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'kword'**

You need to ensure if a post or get request is made, then you can access the request.from keys.
your function would be:
[...]
result=[]
if request.method == "POST":
word=""
word = request.form['kword']
result=getListOfKeyWord(word)
return render_template('advance_search.html',key=result)
return render_template('advance_search.html',key=result)
You can not access request.form["kword"] until a post request is made.

Related

How to combine two dictionaries in Python without duplicates

Hey I'm trying to combine two dictionaries filled with JSON data without duplicates. I'm using Flask and Jinja2 to build an api to fetch json data from an api and post it on a web page, I want to be able to filter based off of tags and then combine the results every time I make a request. Currently I'm able to filter based off of tags chosen by submitting buttons on Jinja but I'm having trouble getting it to combine when I select a new tag, when a new tag is selected it filters only using that tag and doesn't combine the dictionary from the previous result.
main.py:
#app.route('/api', methods=['GET', 'POST'])
def add_tag():
name = request.form['tags']
form = APInameForm()
url= 'https://api.hatchways.io/assessment/blog/posts?tag='+name
try:
api = requests.get(url).json()
api = api['posts']
ilist = []
nlist = []
for i in api:
ilist.append(i)
if not ilist:
output = '{<br>'
output = output + '"error": "Tags parameter is required" <br>'
output = output + '}'
return output
return render_template('/index.html', test=ilist)
except requests.ConnectionError:
return "Connection Error"
#app.route('/')
def index():
return render_template("index.html")
index.html:
{% extends 'base.html' %}
{% block content %}
<form class="text-center pt-3" method="POST" action="/api">
<input type="text" class="form-control" placeholder="Search" name="tags">
<input type="submit" value="Search" />
</form>
<br/><br/><br/>
<h1>Recommended Tags:</h1>
<form class="form-inline" method="POST" action="/api">
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="tech">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="history">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="startups">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="health">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="science">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="design">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="culture">
</input>
</div>
<div class="control">
<input type="submit" class="btn btn-primary mb-2" name="tags" value="history">
</input>
</div>
</form>
<br/><br/><br/>
<code>
{<br>
"posts": [{<br>
{% for item in test %}
"id": {{ item.id }}<br>
"author": {{ item.author }}<br>
"autherId": {{ item.authorId }}<br>
"likes": {{ item.likes }}<br>
"popularity" :{{ item.popularity }}<br>
"reads": {{ item.reads }}<br>
"tags": {{ item.tags }}<br><br>
{% endfor %}
}
]
</code>
{% endblock %}
I am not sure I really understand your question.
But could it be that a simple use of a set will solve your problem?
Sets can't have duplicates
https://www.w3schools.com/python/python_sets.asp
You need to store the previous data somewhere outside these functions to be able to use it in later calls to them. Temporarily, that could be in a variable defined at the top level in your module (.py file).
If you need it to persist longer (across worker threads, sessions or restarts of your custom server), you might need to write to a file or database.
To merge the JSON dictionaries you can use the dict.update method (see official docs).
Given two dict instances d1, d2, calling d1.update(d2) will merge d2 into d1, overwriting values for any keys that are the same.
combined_data = {}
#app.route('/api', methods=['GET', 'POST'])
def add_tag():
response = requests.get(url)
data = response.json()
combined_data.update(data)
# ..now render combined_data

How to delete a comment from the comment section in flask

I have a comment section and I want to allow users to delete their comments, however when I click the delete button the comment doesn't get delete, and over that a new comment with nothing get add.
Here is my python code. When I tried to print "delete" I got none in my terminal window
#app.route("/deletecomment", methods=["GET", "POST"])
#login_required
def deletecomment():
delete = request.args.get("delete")
print(delete)
#if the method is get
if request.method == "GET":
#testing purpose
print("vvv")
print(delete)
#delete the comment
comments = db.execute("DELETE FROM comment WHERE comment=?",delete)
return redirect (url_for("addcomment"))
Here is my html. Is it bad to have a form inside another form?
<form action="/comment" method="get">
<div class="row bootstrap snippets bootdeys">
<div class="col-md-8 col-sm-12">
<div class="comment-wrapper">
<div class="panel panel-info">
<div class="panel-heading">
Comment panel
</div>
<div class="panel-body">
<textarea name="comment" class="form-control" placeholder="write a comment..." rows="3"></textarea>
<br>
<button type="submit" class="btn btn-info pull-right">Post</button>
<div class="clearfix"></div>
<hr>
{% for comments in comments %}
<ul class="media-list">
<!--<button type="submit" class="btn btn-danger">Delete</button>-->
<li class="media">
<a href="#" class="pull-left">
<img src="https://bootdey.com/img/Content/user_1.jpg" alt="" class="img-circle">
</a>
<div class="media-body">
<!--<button type="submit" class="btn btn-danger">Delete</button>-->
<span class="text-muted pull-right">
</span>
<!--<button type="submit" class="btn btn-danger">Delete</button>-->
<strong class="text-success">{{comments.user}}</strong>
<form action="/deletecomment" method="get">
<p name="delete">
{{comments.comment}}
</p>
<button id="but" type="submit" class="btn btn-danger">Delete</button>
</form>
</div>
</li>
</div>
</ul>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</form>
Put the comment ID as a URL parameter in the action URL
<form action="/deletecomment?delete={{comment.id}}" method="get">
and change the controller to use the parameter as the ID in the query.
#app.route("/deletecomment", methods=["GET", "POST"])
#login_required
def deletecomment():
#if the method is get
if request.method == "GET":
delete = request.args.get("delete")
print(delete)
#testing purpose
print("vvv")
print(delete)
#delete the comment
comments = db.execute("DELETE FROM comment WHERE id=?",delete)
return redirect (url_for("addcomment"))

HTML button onclick action with Django function

HTML form on Django.
I want to perform or create web page in which the button performs the action, and in backend I am handling the Django function.
The code of HTML file is:
<form name="bookappointment" class="form" method="POST">
{% csrf_token %}
<br>
<input type="hidden", name="selecteddoctornumber" value="{{i.doctornumber}}">
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-4">
<button class="btn approve" name="approvebtn">Approved</button>
</div>
<div class="col-md-1"></div>
<div class="col-md-4">
<button class="btn notapprove" name="notapprovebtn">Not Approved</button>
</div>
<br>
</div>
<a class="btn cancel" href="requests">Cancel</a>
<br>
</form>
and the other side the Django function is:
if request.method == 'POST':
if request.POST.get('approvebtn'):
for i in doctor:
if pendingDoctorNumber == i.contactNumber:
i.status = 'Approved'
return redirect('request')
if request.POST.get('notapprovebtn'):
for i in doctor:
if pendingDoctorNumber == i.contactNumber:
i.status = 'Not Approved'
return redirect('request')
but its not working any action just get me back to same page
<form action="{% url 'bookappointment' %}" method="POST">
you have to define bookappointment in your urls.py which redirect to views.py where your function lies with name bookappointment.

My Django form is not rendering when I use Bootstrap's modal

I have some trouble with rendering a Django form in a modal. I suspect it is because I need some Ajax to get the url in the browser but I don't know how.
Form:
class TrackedWebsitesForm(forms.ModelForm):
class Meta:
model = TrackedWebsites
fields = "__all__"
View:
def web(request):
if request.method == 'POST':
form = TrackedWebsitesForm(request.POST)
if form.is_valid():
try:
form.save()
return redirect('/websites')
except:
pass
else:
form = TrackedWebsitesForm()
return render(request,'dashboard/create_website.html',{'form':form})
Urls:
urlpatterns = [
path('web', views.web),
create_website.html:
<div id="addEmployeeModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST" class="post-form" action="/web">
{% csrf_token %}
<div class="modal-header">
<h4 class="modal-title">Add website</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<div class="form-group">
{{ form.as_p }}
</div>
<div class="modal-footer">
<input type="button" class="btn btn-default" data-dismiss="modal" value="Cancel">
<input type="submit" class="btn btn-success" value="Add">
</div>
</form>
</div>
</div>
</div>
Some pics
The non working modal form:
Forms works when accessed directly through link:
Can somebody help me out? I render the form fields manually but I just cut it with form.as_p otherwise the question would not validate because there was too much code.
I think that if you can open the modal and you do not visualize the formulary, it is because you are not loading it, try to do this:
Add this in your views.py
def add_employee(request):
form = TrackedWebsitesForm()
return render(request, 'your_template', {'form':form})
Add this in your urls.py
path('employee/add', views.add_employee, name='add_employee'),
in your html
Place this on the page from which you plan to open your modal and wrap your button in a div
<div id="addEmployee">
<a style="float:right" class="btn btn-success" >
<i class="fas fa-fw fa-plus"></i>
<span>Add New Employee</span>
</a>
</div>
<div id="addEmployeeModal" class="modal fade" role="dialog">
</div>
Create a different html for the modal and add an id to your form
<div class="modal-dialog">
<div class="modal-content">
<form id="addEmployeeForm" method="POST" class="post-form" action="/web">
{% csrf_token %}
<div class="modal-header">
<h4 class="modal-title">Add website</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<div class="form-group">
{{ form.as_p }}
</div>
<div class="modal-footer">
<input type="button" class="btn btn-default" data-dismiss="modal" value="Cancel">
<input type="submit" class="btn btn-success" value="Add">
</div>
</form>
</div>
</div>
in your js
$(document).ready(function () {
let my_modal = $("#addEmployeeModal");
const url_form = "/employee/add";
$("#addEmployee a").click(function () {
my_modal.load(url_form, function () {
my_modal.modal("show"); // Open Modal
$("#addEmployeeForm").submit(function (e) {
e.preventDefault(); // Cancel the default action
$.ajax({
method: "POST",
data: $(this).serialize(),
dataType: "json",
url: "/url that handles the request/",
success: function (response) {
my_modal.modal('hide');
},
error: function (response) {
},});
});
});
});
});
This answer will take you to the next question how to respond after sending the data from the modal. Therefore, you must do the following in the view you are handling the request.
First import the following in views.py
from django.http import JsonResponse
And in the view that handles the request copy this
if form.is_valid ():
...
response = JsonResponse ({"message": 'success'})
response.status_code = 201 // indicates that the request has been processed correctly
return response
else:
...
response = JsonResponse ({"errors": form.errors.as_json ()})
response.status_code = 403 // indicates that there was an error processing the request
return response

Django view not getting post param

I know its basic but I got stuckl because of it I internet did not help me.
This is snippet of my django class based view (django 1.7)
def post(self, request,*args, **kwargs):
context = RequestContext(request, {})
print request.POST
print request.POST['search_text']
In html
<form method="post" action="{% url 'storage_place' %}">{% csrf_token %}
<div class="container">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<input type="text" class="form-control" id="search_text" name="search_text " placeholder="Key words...">
</div>
</div>
<div class="col-md-3">
<div class="s_btngroup">
<div class="col-md-6 col-sm-4 col-xs-5">
<input type="submit" class="btn ft_default-btn-red ft_primary-btn-mini" value="Search" />
</div>
</div>
</div>
</div>
</div>
</form>
When I do
print request.POST
It is printing
QueryDict: {u'csrfmiddlewaretoken': [u'GInHZCd4UK8oWjs2txgppCNEof3VC8zy'], u'search_text ': [u'defrghj']}
But in very next line when I do
print request.POST['search_text']
I am getting multivalue dict error.
Please tell me what would be the reason for this.
There's a trailing space after 'search_text ' in the <input.../>'s name attribute in your template:
<input type="..." class="..." id="..." name="search_text "
^
And you'll notice it appears in the QueryDict with the trailing space. You should remove the space.

Categories

Resources