I am trying to use a check box control in a simple django application. Code Logic seems to be fine, But I am getting an empty fruit list ([None, None]). I don't know why it's not working, Can anybody point out the mistake. Thanks in advance
index.html
<div class="form-check">
<input class="form-check-input" type="checkbox" value="Apple" id="apple">
<label class="form-check-label" for="apple">Apple</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="Mango" id="mango">
<label class="form-check-label" for="mango">Mango</label>
</div>
view.py
if request.method == 'POST':
fruit = []
fruit.append(request.POST.get('apple'))
fruit.append(request.POST.get('mango'))
As Daniel mentioned, you have to add a name attribute to form elements, so they are submitted to the server.
index.html
<form method="post">
{% csrf_token %}
<div class="form-check">
<input class="form-check-input" type="checkbox" value="Apple" id="apple" name="fruits">
<label class="form-check-label" for="apple">Apple</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="Mango" id="mango" name="fruits">
<label class="form-check-label" for="mango">Mango</label>
</div>
<button type="submit">Submit</button>
</form>
That way, you can get a list of fruits in your view:
views.py
if request.method == 'POST':
fruits = request.POST.getlist('fruits')
The fruits variable would be a list of check inputs. E.g.:
['Apple', 'Mango']
input elements need a name attribute, otherwise the browser does not send any data.
Related
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
I want to use input field for authentication but if I search for authentication tutorial they are using built-in Django forms which I can't design it using html
You can customize how forms are rendered or you can pretty much write any HTML that you want just make sure your input name attributes match whatever you are accepting on backend.
Here's an example using Bootstrap 4 for styling. Start out by creating a view that subclasses LoginView. In the html file, instead of using {{ form }} or {{ form.username }} & {{ form.password }}, you can supply your own html for the fields. Just make sure your inputs are named the same as in {{ form }}.
views.py:
from django.contrib.auth.views import LoginView
class MyLoginView(LoginView):
template_name = 'login.html'
login.html:
{% block content %}
...
<div id="login-row" class="row justify-content-center align-items-center">
<div id="login-column" class="col-md-6">
<div id="login-box" class="col-md-12">
<form id="login-form" class="form" action="" method="post">
{% csrf_token %}
<div class="form-group">
<label for="username" class="text-white">Username:</label><br>
<input type="text" name="username" id="username" class="form-control" required>
</div>
<div class="form-group">
<label for="password" class="text-white">Password:</label><br>
<input type="password" name="password" id="password" class="form-control" required>
</div>
<div class="form-group">
<input type="submit" name="login" class="btn btn-light btn-md btn-block mt-5"
value="log in">
</div>
</form>
</div>
</div>
</div>
...
{% endblock content %}
I am trying to get the input of the forms by just using requests and no actual django form(I do not need to store this data in a database.) So I am trying to use request.GET.get() method, but so far I have had no luck with it. I am pretty sure that it is something wrong with my HTML, but I could be wrong.
Here is my views.py
if request.method == "GET":
lineGraphInp=request.GET.getlist('lineGraphInp')
lineTableInp=request.GET.get('lineTableInp')
print(lineGraphInp)
print(lineTableInp)
Also, here are my forms
<form method="GET">
<h3>Choose: </h3>
<select class="custom-select" name="lineTableInp">
<option value="myPosition">My Position</option>
<option value="myCompetitors">My Competitors</option>
<option value="top100">Top 100</option>
<option value="bottom100">Bottom 100</option>
</select>
</form>
and
<form method="GET">
<h3>Choose: </h3>
<div style="margin-left:15px;">
<div class="form-check form-check-inline">
<input name="lineGraphInp" class="form-check-input" type="checkbox" value="myPosition">
<label class="form-check-label" for="inlineCheckbox1">My Position</label>
</div>
<div class="form-check form-check-inline">
<input name="lineGraphInp" class="form-check-input" type="checkbox" value="myCompetitors" >
<label class="form-check-label" for="inlineCheckbox2">My Competitors</label>
</div>
<div class="form-check form-check-inline">
<input name="lineGraphInp" class="form-check-input" type="checkbox" value="top100">
<label class="form-check-label" for="inlineCheckbox3">Top 100</label>
</div>
<div class="form-check form-check-inline">
<input name="lineGraphInp" class="form-check-input" type="checkbox" value="bottom100">
<label class="form-check-label" for="inlineCheckbox3">Bottom 100</label>
</div>
</div>
</form>
You have not specified form acion
Eg.
<form method="GET" action="/">
Content Here
</form>
Please make sure that you mention that action it will not work unless you will mention it
I think these only a issue..!!!
Thank You
really struggling with this bad request from flask. I know normally it caused by flask not finding the [key] in the form.. However, I've checked my form and python code 40 times and cannot see any reason that would be the case.. I have commented out each line of the python code that references request.form. I have done it 1 by 1 and I still get a bad request. However when I comment out all the lines the bad request goes away.. Any thought would be wonderful..
Python code;
if request.method == 'POST':
form = 'Add Package Form'
clientId = request.form['id']
date = request.form['date2']
strPrice = request.form['price']
price = float(strPrice)
adultlessons = request.form['adult']
juniorlessons = request.form['junior']
shortlessons = request.form['short']
playinglessons = request.form['playing']
notes = request.form['notes']
form..
<form action="/addpackage" method="post" class="sky-form">
<fieldset>
<section>
<label class="label">Select Package Date</label>
<label class="input">
<i class="icon-append fa fa-calendar"></i>
<input type="text" name="date2" id="date">
</label>
</section>
<div style="margin: -25px"></div>
<fieldset>
<section>
<label class="label">Price</label>
<label class="input">
<input type="text" name="price">
</label>
</section>
<section>
<label class="label">Adult Lessons</label>
<label class="input">
<input type="text" name="adult">
</label>
</section>
<section>
<label class="label">Junior Lessons</label>
<label class="input">
<input type="text" name="junior">
</label>
</section>
<section>
<label class="label">Short Game Lessons</label>
<label class="input">
<input type="text" name="short">
</label>
</section>
<section>
<label class="label">Playing Lessons</label>
<label class="input">
<input type="text" name="playing">
</label>
</section>
<section>
<label class="label">Notes</label>
<label class="textarea textarea-expandable">
<textarea rows="3" name="notes"></textarea>
</label>
<div class="note"><strong>Note:</strong> expands on focus.</div>
</section>
</fieldset>
</fieldset>
<!-- hidden client id -->
<input type="hidden" name="id" value="{{ client.id }}">
<!-- /hidden client id -->
<footer>
<button type="submit" name="addpackage" value="package" class="button">Add Package</button>
</footer>
</form>
This is something of a half-answer, but it was too long for a comment.
If you enable debugging in your Flask app you should get a detailed traceback indicating exactly where the problem is occurring (both in the browser and on your console).
If your application currently has something like:
app.run()
Just set the debug parameter to true:
app.run(debug=True)
If after enabling debugging you're still not sure what's causing the problem, update your question to include the traceback.
For what it's worth, if I dump your form and your code into a simple Flask app, it all seems to work just fine as long as I provide a numeric value for the price field.
Usually you'll get a 400 Bad Request in Flask while submitting a form when you try and access a form key in the request object that doesn't exist.
This is because the request.form object inherits its __getitem__ method the Multidict class in the werkzeug.datastructures module which raises a BadRequestKeyError when a key doesn't exist.
You should give the form data a default value to avoid HTTP 400 error, like this:
default_value = True
is_public = request.form.get('public', default_value)
However, I recommend you to use Flask-WTF.
With Flask-WTF, your code can be simplify to this (an example):
import ...
app = Flask(__name__)
class EditProfileForm(Form):
name = StringField('name', validators=[Length(0, 64)])
location = StringField('city', validators=[Length(0,64)])
website = StringField('website', validators=[Length(0,64), render_kw={"placeholder": "http://..."})
about_me = TextAreaField('Bio', validators=[Length(0,2000)], render_kw={"placeholder": "I'm......"})
submit = SubmitField(u'submit')
#app.route('/edit-profile', methods=['GET', 'POST'])
def edit_profile():
form = EditProfileForm()
if form.validate_on_submit():
current_user.name = form.name.data
current_user.location = form.location.data
current_user.website = form.website.data
current_user.about_me = form.about_me.data
db.session.add(current_user)
flash('Update success!', 'success')
return redirect(url_for('.user', username=current_user.username))
return render_template('edit_profile.html', form=form)
In your html file:
<form method="POST" action="/">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name() }}
{{ form.location.label }} {{ form.location() }}
...
</form>
By the way, if you use Flask-Bootstrap, you can just use one line to render the whole form:
{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}
I hope it will help.
I'm a bit confused with all the django stuff and forms, I hope you can help me.
I'm migrating a cmd line app to django, and I think I don't need to mess with models (db) atm. I just would like to pass the parameters filled in a form to a python script that use these fields as parameters. I would like to keep my html code and skip render the form with a python form class since it has a lot of css code inside each one.
At the moment I have this form:
<form class="nobottommargin" id="template-contactform" name="template-contactform" action="{% url 'get_data' %}" method="post">
{% csrf_token %}
<div class="col_half">
<label for="name">Project Name <small>*</small></label>
<input type="text" id="name" name="name" value="{{ current_name }}" class="sm-form-control required" />
</div>
<div class="col_half col_last">
<label for="group">Project Group <small>*</small></label>
<input type="text" id="group" name="group" value="{{ current_group }}" class="required sm-form-control" />
</div>
<div class="clear"></div>
<div class="col_half">
<label for="version">Project Version<small>*</small></label>
<input type="text" id="version" name="version" value="{{ current_version }}" class="required sm-form-control" />
</div>
<div class="col_half col_last">
<label for="pType">Project Type<small>*</small></label>
<select id="pType" name="pType" class="required sm-form-control">
<option value="">-- Select One --</option>
<option value="bundle">Bundle</option>
<option value="multiple">Multiple</option>
<option value="git">Git</option>
</select>
</div>
<div class="col_half">
<label for="pPath">Project path<small>*</small></label>
<input type="text" id="pPath" name="pPath" value="{{ current_path }}" class="required sm-form-control" />
</div>
<div class="clear"></div>
<div class="col_full hidden">
<input type="text" id="template-contactform-botcheck" name="template-contactform-botcheck" value="" class="sm-form-control" />
</div>
<div class="col_full" style="margin: 50px 0 0 0 ">
<button class="button button-3d nomargin" type="submit" id="template-contactform-submit" name="template-contactform-submit" value="submit">Create Project</button>
</div>
</form>
So, I want to figure out what's the best way to write the get_data function. I also need some sort of custom validation about some fields that involves other checks that exceeds the basic checks, such as max_chars on each field. That means I need to create some sort of my own form.is_valid() function.
Hope you can help me!
Regards