Python/Flask, request ID from dropdownlist populated options with SQLite - python

I'm trying to get the IDs selected with a dropdown and add it to my table without the use of JSON but I keep getting the same error :
werkzeug.exceptions.HTTPException.wrap..newcls: 400 Bad
Request: KeyError: 'nomFabri'
I have three tables:
https://i.stack.imgur.com/W7v7x.png
(can't post image yet, sadly)
Thought it would work fine and tried to mess around with my columns, without much success. Most of what I got from my researchs are to use JSON isn't there a workaround without using it ?
Here the code
#bp.route('/Appareil', methods=['GET', 'POST'])
def Appareil():
db = get_db()
materielTypes = db.execute(
'SELECT * FROM t_type'
).fetchall()
fabriquants = db.execute(
'SELECT * FROM t_fabriquant'
).fetchall()
return render_template('materiel/appareil.html',
materielTypes=materielTypes, fabriquants=fabriquants)
#bp.route('/AddAppareil', methods=['GET', 'POST'])
def AddAppareil():
if request.method == 'POST':
nomModele = request.form['nomModele']
numeroProduit = request.form['numeroProduit']
nomFabri = request.form['nomFabri']
matType = request.form['matType']
error = None
if not nomModele:
error = 'Faux.'
if error is not None:
flash(error)
else:
db = get_db()
db.execute(
'INSERT INTO t_appareil (nomModele, numeroProduit, nomFabri, mattype)'
' VALUES (?, ?, ?, ?)',
(nomModele, numeroProduit, nomFabri, matType,)
)
db.commit()
return redirect(url_for('materiel.appareil'))
return render_template('materiel/appareil.html')
And here the form
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}nouvel appareil{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post" class="insertdata" action="/AddAppareil">
<select>
{% for materielType in materielTypes %}
<option name="matType" id="matType" value="{{ request.form['id_type'] }}">{{ materielType['materielType'] }}</option>
{% endfor %}
</select>
<select>
{% for fabriquant in fabriquants %}
<option name="nomFabri" id="nomFabri" value="{{ request.form['id_fabriquant']] }}">{{ fabriquant['nomFabr'] }}</option>
{% endfor %}
</select>
<input type="text" name="nomModele" id="nomModele" placeholder="nom du Modele" value="{{ request.form['nomModele'] }}" required>
<input type="text" name="numeroProduit" id="numeroProduit" placeholder="Numéro de série" value="{{ request.form['numeroProduit'] }}" required>
<input type="submit" value="Save">
</form>
{% endblock %}
Thanks for any help provided :)

You need to add name value to select <select name='mateType'>...</select>, <select name='nomFabri'>...</select>. Another problem, you need to remove value="{{ request.form['nomModele'] }}" from select and input fields.
Your python code will be similar to this:
#bp.route('/AddAppareil', methods=['GET', 'POST'])
def AddAppareil():
nomModele = ''
numeroProduit= ''
nomFabri= ''
matType= ''
if request.method == 'POST':
nomModele = request.form['nomModele']
numeroProduit = request.form['numeroProduit']
nomFabri = request.form['nomFabri']
matType = request.form['matType']
error = None
if not nomModele:
error = 'Faux.'
if error is not None:
flash(error)
else:
db = get_db()
db.execute(
'INSERT INTO t_appareil (nomModele, numeroProduit, nomFabri, mattype)'
' VALUES (?, ?, ?, ?)',
(nomModele, numeroProduit, nomFabri, matType,))
db.commit()
return redirect(url_for('materiel.appareil'))
db = get_db()
materielTypes = db.execute(
'SELECT * FROM t_type'
).fetchall()
fabriquants = db.execute(
'SELECT * FROM t_fabriquant'
).fetchall()
return render_template('materiel/appareil.html',
nomModele = nomModele, numeroProduit=numeroProduit,
nomFabri=nomFabri, matType=matType,
materielTypes=materielTypes,fabriquants = fabriquants)
And the appareil.html file will be similar to this:
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}nouvel appareil{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post" class="insertdata" action="/AddAppareil">
<select name='matType'>
{% for materielType in materielTypes %}
<option value="{{ materielType['id_type'] }}"
{% if matType == materielType['id_type'] %} selected {% endfor %} >
{{ materielType['materielType'] }}
</option>
{% endfor %}
</select>
<select name="nomFabri" id="nomFabri">
{% for fabriquant in fabriquants %}
<option value="{{ fabriquant['id_fabriquant'] }}"
{% if nomFabri == fabriquant['id_fabriquant'] %} selected {% endfor %}>
{{ fabriquant['nomFabr'] }}
</option>
{% endfor %}
</select>
<input type="text" name="nomModele" id="nomModele" placeholder="nom du Modele"
value="{{ nomModele }}" required>
<input type="text" name="numeroProduit" id="numeroProduit"
placeholder="Numéro de série" value="{{ numeroProduit }}" required>
<input type="submit" value="Save">
</form>
{% endblock %}
And you need to add some default values for the form fields:
#bp.route('/Appareil', methods=['GET', 'POST'])
def Appareil():
#...
return render_template('materiel/appareil.html',
materielTypes=materielTypes, fabriquants=fabriquants
nomModele = '',
numeroProduit= '',
nomFabri='',
matType='')

Related

How to get all objects of a choice field?

I'm doing a search form where an user selects the category and the type of product which is a choice field of the Product model, product_type = models.CharField(max_length=30, choices=TYPE, default='Physical'). I can get the categories but not the choices in TYPE to add to the form.
choices.py
TYPE = [
('PHYSICAL', _('Physical')),
('DIGITAL', _('Digital')),
]
views.py
from .choices import TYPE
def is_valid_queryparam(param):
return param != '' and param is not None
def FilterView(request):
qs = Product.objects.all()
categories = Category.objects.all()
ptypes = Product.product_type.all() # The problem line
category = request.GET.get('category')
ptype = request.GET.get('ptype')
if is_valid_queryparam(category) and category != 'Choose...':
qs = qs.filter(category__name=category)
if is_valid_queryparam(ptype) and ptype != 'Choose...':
qs = qs.filter(product_type=ptype)
context = {
'queryset': qs,
'categories' : categories,
'ptypes' : ptypes,
}
return render(request, 'categories/display_query.html', context)
base.html
<div>
<h3>Advanced Search</h3>
<form method="GET" action="{% url 'filter-view' %}">
<div>
<label for="category">Category</label>
<select name="category">
<option selected>Choose...</option>
{% for cat in categories %}
<option value="{{ cat }}">{{ cat }}</option>
{% endfor %}
</select>
</div>
<div>
<label for="ptype">Product type</label>
<select name="ptype">
<option selected>Choose...</option>
{% for type in ptype %}
<option value="{{ type }}">{{ type }}</option>
{% endfor %}
</select>
</div>
<button type="submit">Search</button>
</form>
</div>
display_query.html
{% extends 'products/base.html' %}
{% block content %}
<div>
<ul>
{% for product in queryset %}
<li>
{{ product.title }}
<span>Author: {{ product.author.username }}</span>
</li>
{% endfor %}
</ul>
</div>
{% endblock content %}
You can use the given code:
p_types_keys = [i[0] for i in TYPE]
p_types_values = [i[1] for i in TYPE]
ptype_dict = dict(zip(p_types_keys, p_types_values))
In the line will return all the keys of your "TYPE"
The second line will return all the keys of your "TYPE"
The Third line will return the key-value pair of your types to add form.

Django search form for filtering

I am currently doing a search using forms
This is my views.py
class HomeView(generic.ListView):
model = Consultant
template_name = 'sogeti/home.html'
def get_queryset(self):
query = self.request.GET.get('q')
if query:
return Consultant.objects.filter(
Q(first_name__icontains=query) |
Q(last_name__icontains=query) |
Q(group__title_techGroup__contains=query) |
Q(practices__title_practice__contains=query)
)
else:
return Consultant.objects.all()
and this is my home.html
<form action="" method="get" class="form-inline">
<input type="text" name="q" placeholder="Enter Keyword" value="{{ request.GET.q }}" class="form-control">
<select name="filter" class="form-control">
<option value="all">All</option>
<option value="people">People</option>
<option value="certification">Certification</option>
<option value="skillset">Skillset</option>
</select>
<input type="submit" value="Search" class="btn btn-default">
</form>
<ol style="padding-left: 15px">
{% for consultant in object_list %}
<li>
{{ consultant.first_name }}, {{ consultant.last_name }} </br>
Technology Group: {{ consultant.group }} </br>
Primary Practice: {{ consultant.practices }}
<hr style="margin-left: 0">
</li>
{% endfor %}
</ol>
My first problem is that when it tries to search something (Eg: bla) that is not in my database, it returns a blank screen. Nothing at all. Tried searching but could not get any answers.
My second problem is how am I able to specify my search using HTML select and options to filter. As you can see from my home.html I have the tag with option value but no idea how to utilize it for Django.
Thank you so much for your help! Really appriciate it.
About first issue, you actually can double check the object_list before iterate over it, e.g:
{% if object_list %}
<ul>
{% for item in object_list %}
<p>{{item.value}}</p>
{% endfor %}
</ul>
{% else %}
<p>Empty!</p>
{% endif %}
If you're unable to search, then double check your query by using some tools like django-debug-toolbar to take a look at the queries.
About the second question, I recommend you to use Django Form instead, like so:
Create forms.py:
from django.forms import Form, ChoiceField, CharField
class FilterForm(Form):
FILTER_CHOICES = (
('all', 'All'),
('people', 'People'),
('certification', 'Certification'),
('skillset', 'Skillset'),
)
search = CharField(required=False)
filter_field = ChoiceField(choices=FILTER_CHOICES)
Then your view (views.py):
class HomeView(ListView):
model = Consultant
template_name = 'home.html'
def get_queryset(self):
query = self.request.GET.get('search')
filter_field = self.request.GET.get('filter_field')
# Do your filter and search here
return Consultant.objects.all()
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['form'] = FilterForm(initial={
'search': self.request.GET.get('search', ''),
'filter_field': self.request.GET.get('filter_field', ''),
})
return context
and finally your template (templates/home.html):
<form class="row">
{{ form.search }}
{{ form.filter_field }}
<input type="submit" class="btn btn-default" value="Search">
</form>
Hope that would be helpful!
For the first issue, if there is nothing in the database it is returning an empty queryset so if you include
{% if object_list %}
do stuff
{% else %}
No results match your search
{% endif %}
For the second it depends on what you're trying to do, but let's suppose it is a
specific field you're searching.
search_choice = self.request.GET.get('filter')
choice_query = Q(search_field=search_choice)
Then simply add this to your query
views.py
class HomeView(generic.ListView):
model = Consultant
template_name = 'sogeti/home.html'
def get_queryset(self):
queryset = super().get_queryset()
q = self.request.GET.get('q')
if q:
queryset = queryset.filter(
Q(first_name__icontains=q) |
Q(last_name__icontains=q) |
Q(group__title_techGroup__contains=q) |
Q(practices__title_practice__contains=q)
)
filter = self.request.GET.get('filter')
if filter == 'people':
pass
elif filter == '...':
# do sth
return queryset
html
<form action="" method="get" class="form-inline">
<input type="text" name="q" placeholder="Enter Keyword" value="{{ request.GET.q }}" class="form-control">
<select name="filter" class="form-control">
<option value="all">All</option>
{% if request.GET.filter == 'people' %}
<option value="people" selected>People</option>
{% else %}
<option value="people">People</option>
{% endif %}
{% if request.GET.filter == 'certification' %}
<option value="certification" selected>Certification</option>
{% else %}
<option value="certification">Certification</option>
{% endif %}
{% if request.GET.filter == 'skillset' %}
<option value="skillset" selected>Skillset</option>
{% else %}
<option value="skillset">Skillset</option>
{% endif %}
</select>
<input type="submit" value="Search" class="btn btn-default">
</form>
<ol style="padding-left: 15px">
{% for consultant in object_list %}
<li>
{{ consultant.first_name }}, {{ consultant.last_name }} </br>
Technology Group: {{ consultant.group }} </br>
Primary Practice: {{ consultant.practices }}
<hr style="margin-left: 0">
</li>
{% empty %}
No result match q=`<b>{{ request.GET.q }}</b>` & filter=`{{ request.GET.filter }}`
{% endfor %}
</ol>

Unable to get value selected in python from a dropdown using Flask

This question could be a duplicate but I have checked all the answers of such related questions and I haven't been able to solve it.
I am trying to get the value from a dropdown menu which consists of numbers. Then I want to compare the numbers with a value and display a text based on the comparison.
Eg
if value_selected_from_dropdown >3
display text
I am unable to get the text to display or even print the value of the option selected.
Here is the python file, web_plants.py
from flask import Flask, render_template,request, redirect, url_for
app = Flask(__name__)
def template(title = "HELLO!", text = ""):
templateDate = {
'text' : text
}
return templateDate
#app.route("/threshold", methods=['POST'])
def threshold():
tvalue= (request.form.get['tvalue']) #get value from dropdown
msg= ""
if tvalue>3:
msg= "rating above 3"
templateData = template(text = msg) #display text using template()
#templateData = template(text = tvalue) #tried to print the value selected
return render_template('index.html', **templateData)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80, debug=True)
index.html:
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='style.css')}}" />
</head>
<body>
<h2> {{ text }} </h2>
<form action= "{{ url_for('threshold') }}" method="post>"
<p>
<select name= 'tvalue'>
<option value="10">10</option>
<option value="11">11</option>
<option value="15">15</option>
<option value="2">2</option>
<option value="1">1</option>
</select>
</p>
</form>
</body>
</html>
There are several ways to achieve this. Either you can give logic to the template itself or you can add the logic in the function threshold.
index.html
<h2> {{text}} </h2>
<form action= "{{ url_for('threshold') }}" method="POST">
<select name= 'tvalue'>
{% for tvalue in tvalues %}
{% if selected_tvalue == tvalue %}
<option value="{{ tvalue }}" selected='selected'>{{ tvalue }}</option>
{% else %}
<option value="{{ tvalue }}" >{{ tvalue }}</option>
{% endif %}
{% endfor %}
</select>
<input type="submit" value="Submit" />
</form>
OR,
{% if selected_tvalue > 3 %}
<h2> Selected value is greater than 3 </h2>
{% else %}
<h2> Selected value is less than or equal to 3 </h2>
{% endif %}
<form action= "{{ url_for('threshold') }}" method="POST">
<select name= 'tvalue'>
{% for tvalue in tvalues %}
{% if selected_tvalue == tvalue %}
<option value="{{ tvalue }}" selected='selected'>{{ tvalue }}</option>
{% else %}
<option value="{{ tvalue }}" >{{ tvalue }}</option>
{% endif %}
{% endfor %}
</select>
<input type="submit" value="Submit" />
</form>
server.py
def template(title = "HELLO!", text = ""):
templateDate = {
'text' : text,
'tvalues' : getTValues(),
'selected_tvalue' : -1
}
return templateDate
def getTValues():
return (10, 11, 15, 2, 1)
#app.route("/threshold", methods=['POST', 'GET'])
def threshold():
tvalue= -1 #default value
msg = ''
if request.method == "POST":
tvalue = int(request.form['tvalue'])
if tvalue> 3:
msg= "rating above 3"
#generating template data
templateData = template(text = msg)
templateData['selected_tvalue'] = tvalue
return render_template('index.html', **templateData)
Then access your form at path /threshold. I hope it helps.
In your html after your drop down block you may need something like
<input type="submit">
which will trigger the submit. I am not sure, selecting a value alone triggers the form submit.
By the way where are you rendering your page initially ? I would have something like:
#app.route('/')
#app.route('/index')
def index():
return render_template('index.html')
in the python code. There to get the value, I would try
tvalue= request.args.get('tvalue')
Well not 'form' but 'args', and normal brackets instead of squared ones. Finally the function where you are going to handle that 'templateData' might be missing too.
last note:
you might need GET method too:
#app.route("/threshold", methods=['GET', 'POST'])

Django - Taking value from POST request

I have a list of zones, identified by id (integer).
How can I get the zone that generated the post request?
manual.html
{% if zone_list %}
<ul>
{% for z in zone_list %}
<b><p>{{z.name}}</p></b>
<form action="" method="post">
{% csrf_token %}
<input type="submit" name="{{z.id}}" value="ON"/>
<input type="submit" name="{{z.id}}" value="OFF"/><br>
<br>
<label>Tiempo</label>:
<input type="integerfield" name="Tiempo">
<input type="submit" name="{{z.id}}" value="Start">
</form>
{% endfor %}
</ul>
{% endif %}
In the views.py I have to change the 1 for something that dynamically represents the zone
views.py
def manual(request):
if request.POST.has_key('1'):
z = Zone.objects.get(id = 1)
keyword = request.POST.get("1","")
if keyword == "ON":
#do something
if keyword == "OFF":
#do something
if keyword == "Start":
#do something
zone_list = Zone.objects.all()
context = {'zone_list':zone_list}
return render(request, 'irrigation_controller/manual.html', context)
I solved the problem. As themanatuf said, I used a hidden input field with the zone_id.
manual.html
{% if zone_list %}
{% for z in zone_list %}
<b><p>{{z.name}}</p></b>
<form action="" method="post">
{% csrf_token %}
<input type="hidden" name="zone_id" value="{{z.id}}">
<input type="submit" name="order" value="ON"/>
<input type="submit" name="order" value="OFF"/><br>
<br>
<label>Tiempo</label>:
<input type="integerfield" name="Tiempo">
<input type="submit" name="order" value="Start">
</form>
{% endfor %}
{% endif %}
And in the view I read the zone_id and the order.
views.py
def manual(request):
if request.POST.has_key('zone_id'):
z = Zone.objects.get(id = request.POST.get("zone_id",""))
keyword = request.POST.get("order","")
if keyword == "ON":
z.irrigation_on()
if keyword == "OFF":
z.irrigation_off()
if keyword == "Start":
tiempo = request.POST['Tiempo']
tiempo = float(tiempo)
irrigation_time.delay(z.id, tiempo)
zone_list = Zone.objects.all()
context = {'zone_list':zone_list}
return render(request, 'irrigation_controller/manual.html', context)

Storing variables with sessions django

This is my code:
views.py:
def some_function(request):
form = MyForm(request.POST)
if request.method == 'GET':
return render_to_response('template.html', RequestContext(request, {'form': form}))
elif request.method == 'POST':
input_word = request.POST['input_word']
if 'word_choice' in request.POST:
word_choice = request.POST['word_choice']
else:
word_choice = ''
var1 = HelperClass(input_word).func1()
table1 = HelperClass(input_word).table_one()
table2 = HelperClass(input_word).table_two()
word_selected = word_choice
content = {
'form': form,
'input_word': input_word,
'var1': var1,
'table1' : table1,
'table2' : table2,
'word_selected': word_selected,
}
return render_to_response('result_template.html', RequestContext(request, content))
else:
raise Http404
This is result_template.html:
{% block content %}
<form action="/admin/find-word/" method="post">
{% csrf_token %}
<input id="input_word" type="text" name="input_word" maxlength="100"><br />
<input type="submit" value="Submit" />
<form />
<h1>{% trans "You entered" %} "{{ input_word }}" </h1>
<p>{{ var1 }}</p>
<form action="/admin/find-root/" method="post">
{% csrf_token %}
<h3>{% trans "Table2" %}</h3>
{% for word in table2 %}
# Get info from database and display it on the current template.
<input type="radio" name='word_choice' value="{{ word }}"> {{ word }}<br>
{% endfor %}
<h3>{% trans "Table3" %}</h3>
{% for word in table3 %}
{# Get info from database and display it on the current template. #}
<input type="radio" name='word_choice' value="{{ word }}"> {{ word }}<br>
{% endfor %}
<p>{% trans "You selected: " %}{{ word_selected }}</p>
{# Submit the word of choice.#}
<input type="submit" value="Search">
<form />
{% endblock %}
I need to add code to views.py, so that:
it shows result, that was rendered after submitting the first form
(when assining input_word)
new result shows, when resubmitting the first form
when submitting second form redirect to success_template.html (this part I can do myself)
I know, that I need to use sessions here. I've tried different things, but I'm lost now.
Create a session variable in django as follows.
request.session['key'] = value
Access it by
request.session['key'] # or
request.session.get('key')
remove it by
del request.session['key']
In django you can simply assign values to sessions with:
request.session['value']
In your case you'd have to replace the word_selected variable with request.session['word_selected']

Categories

Resources