Flask Select field - Not a valid choice - python

I have the following code in form.py
OPTIONS = ['Option1', 'Option2', 'Option3']
class Test_Form(Form):
test = SelectField('Dropdown', coerce= str,
choices=[(f, f) for f in OPTIONS])
submit = SubmitField('Submit')
And the following code in my template
<div class = "control-group">
<label class="control-label">
{{ form.test.label }} </label>
{% if form.test.errors %}
{% for error in form.test.errors %}
<p class="error-message"> {{ error }}</p>
{% endfor %}
{% endif %}
<div class="controls">
<select name=form.test.label width="80px">
{% for i,j in form.test.choices %}
<option value = {{ i }} > {{ j }} </option>
{% endfor %}
</select>
</div>
</div>
Following is my view function
def show_logs():
my_form = Test_Form()
if request.method == "POST":
if logs_form.validate() == False:
return render_template('test.html', form = my_form)
else:
return my_form.test.data
#return render_template('test_success.html', output = output_list)
elif request.method == "GET":
return render_template('test.html', form = my_form)
I get a "Not a Valid Choice" every time I submit the form. I went through the previous questions on SO and tried coerce = str but I still get the same message. What am I missing here?

I tried your code and it works perfectly on my end. The only thing I changed however was your template code as yours was incomplete. It had no submit button and no <form> tag declaration.
This is the template code that I used:
<form action="" method='post'>
{{ form.hidden_tag() }}
<ul class="request_form">
{%if form.errors%}
Please correct the following fields:
{%for each in form.errors%}
<br>{{each}}
{%endfor%}
{%endif%}
{%for each in form%}
{%if each.name != "csrf_token" and each.name!="submit"%}
<li>
<label>{{each.name}}</label>
{{each()}}
</li>
{%endif%}
{%endfor%}
<li/>{{form.submit}}
</ul>
</form>
Also, in your view, you're checking for logs_form.validate() when it should be my_form.validate()
I hope this solves your problem.

Related

Adding file and fetching data from model to save in another model in django 3.0

I'm trying to add a file in a form. In my views.py i am trying to fetch subject_id from subject model and session_year_id from SessionYearModel to save the data in my Notes model . But it is not processing.and gives a message of "Failed to add Notes". How to do that?
Below is the code.
My views.py
def staff_add_notes_save(request):
if request.method != "POST":
return HttpResponseRedirect(reverse("staff_apply_leave"))
else:
subject_id = request.POST.get("subject_id")
session_year_id = request.POST.get("session_year_id")
notesfile1 = request.FILES["notesfile"]
subject_model = Subjects.objects.filter(id=subject_id)
session_model = SessionYearModel.object.filter(id=session_year_id)
try:
notes = Notes.objects.create(subject_id=subject_model,session_year_id=session_model,notesfile=notesfile1)
notes.save()
messages.success(request, "Successfully added Notes")
return HttpResponseRedirect(reverse("staff_add_notes"))
except:
messages.error(request, "Failed to add Notes")
return HttpResponseRedirect(reverse("staff_add_notes"))
staff_add_notes.html(TEMPLATE)
<form role="form" action="/staff_add_notes_save" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label>Subject </label>
<select class="form-control" name="subject" id="subject">
{% for subject in subjects %}
<option value="{{ subject.id }}">{{ subject.subject_name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label>Session Year</label>
<select class="form-control" name="session_year" id="session_year">
{% for session_year in session_years %}
<option value="{{ session_year.id }}">{{ session_year.session_start_year }} TO {{session_year.session_end_year }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label>Add notes</label>
<input type="file" name="notesfile" class="form-control">
</div>
<div class="form-group">
{% if messages %}
{% for message in messages %}
{% if message.tags == 'error' %}
<div class="alert alert-danger" style="margin-top:10px">{{ message }}</div>
{% endif %}
{% if message.tags == 'success' %}
<div class="alert alert-success" style="margin-top:10px">{{ message }}</div>
{% endif %}
{% endfor %}
{% endif %}
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary btn-block">Add Notes</button>
</div>
</form>
EDIT 1
After removing try and except, below is code of views.py
def staff_add_notes_save(request):
if request.method != "POST":
return HttpResponseRedirect(reverse("staff_apply_leave"))
else:
subject_id = request.POST.get("subject")
session_year_id = request.POST.get("session_year")
notesfile1 = request.FILES["notesfile"]
subject_model = Subjects.objects.filter(id=subject_id)
session_model = SessionYearModel.object.filter(id=session_year_id)
notes_model = request.FILES["notesfile"]
notes = Notes.objects.create(subject_id=subject_model,session_year_id=session_model, notesfile1=notes_model)
notes.save()
messages.success(request, "Successfully added Notes")
return HttpResponseRedirect(reverse("staff_add_notes"))
Error:
I assume subject_model contains one Subject and session_model contains one SessionYearModel.
Change your query for getting those to:
subject_model = Subjects.objects.get(id=subject_id)
session_model = SessionYearModel.objects.get(id=session_year_id)
Also, you don't want to try, except with specific exception. Any failure will be caught with this and thus does not give you any idea on what went wrong. Either catch a specific exception of remove the try, except.
The create method of the queryset api already saves the model. the save() method is therefore not necessary after calling create in your case.
Edit 1
The values in your post request dict are based on the name attributes of the field. Therefore, change subject_id and session_year_id to this:
subject_id = request.POST.get("subject")
session_year_id = request.POST.get("session_year")
Edit 2
class SessionYearModel(models.Model):
id=models.AutoField(primary_key=True)
session_start_year=models.DateField()
session_end_year=models.DateField()
object=models.Manager()

Getting data from the session[] Python, Flask

I'm trying to make simple cart system to the online shop using Python and framework - Flask.
I'm getting data from form in products.html then writing it into the session. I have a problem with getting this data and returning it to the cart.html - I'm get just clear page instead of names of the products i added to the cart.
products.html
{% for el in products %}
<p>Name {{ el.product_name }}</p>
<p>Description {{ el.product_description }}</p>
<p>Image </p> <img width="200" height="200" src="data:;base64,{{ el.product_img }}">
<p>Cost: {{ el.product_cost }} тенге.</p>
<form method="post" action="/cart">
<input type="hidden" name="cart_prod_name" value="{{ el.product_name }}">
<input type="submit" value="Add to cart">
</form>
{% endfor %}
Python function cart():
#app.route('/cart', methods=['POST', 'GET'])
def cart():
if 'cart' not in session:
session['cart'] = []
if request.method == 'POST':
cart_prod_name = request.form['cart_prod_name']
session['cart'] += cart_prod_name
return redirect('/cart')
if request.method == 'GET':
cart_products = session['cart']
return render_template('cart.html', cart_products=cart_products)
cart.html:
{% for cart_product in cart_products %}
<p>{{ cart_product.order_prod_name }}</p>
{% endfor %}
From flask.session docs:
Be advised that modifications on mutable structures are not picked up
automatically, in that situation you have to explicitly set the
attribute to True yourself.
your carts holder object is a mutable structure == list so you have to set after changes
session.modified = True
I sloved that problem. Exactly I needed to iterate cart_product in cart_roducts and output cart_product and don't call it to output order_prod_name.
Fixed cart.html:
{% for cart_product in cart_products %}
<p>{{ cart_product }}</p>
{% endfor %}

List with checked checkboxes in Django

So, i want to get the checked checkboxes items ids as a list and show them on another page. But when i get to that specific page i get the value 'None' instead of the list of ids. What could go wrong? I tried some different versions from another questions already posted on the site, but the result was the same.
Here is the code:
models.py:
from django.db import models
class afirmatii(models.Model):
text = models.CharField(max_length = 250)
def __str__(self):
return self.text
views.py:
def exam(request):
if request.method == 'POST':
checks = request.POST.get('selected[]')
request.session['checks2'] = checks
context = {
'title' : 'Title1',
'aff': afirmatii.objects.order_by('id')
}
return render(request, 'pages/exam.html', context)
def result(request):
checks = request.session.get('checks2')
context = {
'title' : 'Title2',
'checks': checks
}
return render(request, 'pages/result.html', context)
exam.html:
{% extends "./base.html" %}
{% block content %}
<div class="text-break">
<form action="{% url 'result' %}" method="POST">
{% csrf_token %}
{% for q in aff %}
<div class="border mb-3 rounded-sm bg-light p-2">
<div class="custom-control custom-checkbox checkbox-info">
<input type="checkbox" class="custom-control-input" id="{{ q.id }}" name = "selected[]">
<label class="custom-control-label" for="{{ q.id }}" name = 'selected[]'> {{ q.text }} </label>
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-md btn-outline-info">Next</button>
</form>
</div>
{% endblock content %}
result.html:
{% extends "./base.html" %}
{% block content %}
<body>
<div class="text-center">
<p class="pb-5"> {{ checks }} </p><br>
<div class="row">
<div class="col">
Home
</div>
<div class="col">
Learn more
</div>
</div>
</div>
</body>
{% endblock content %}
You can try use FORMSETS A formsets is a layer of abstraction to work with multiple forms on the same page.
You can paint the list of questions according to records in the table and get ids (or other fields) of the marked answers
forms.py
class ExamForm(forms.Form):
checkbox = forms.BooleanField(required=False)
id = forms.CharField(widget=forms.HiddenInput)
text = forms.CharField(widget=forms.HiddenInput)
views.py
from django.shortcuts import render
from django.forms import formset_factory
from .forms import *
def exam(request):
aff = afirmatii.objects.order_by('id')
exam_formset = formset_factory(ExamForm, extra=0)
formset = exam_formset(initial=[{'id': x.id, 'text': x.text} for x in aff])
checks = []
if request.method == 'POST':
formset = exam_formset(request.POST)
if formset.is_valid():
for form in formset.forms:
if form.cleaned_data.get('checkbox', None):
checks.append(form.cleaned_data)
context = {
'formset': formset,
'checks': checks,
}
return render(request, 'pages/exam.html', context)
exam.html
{% if not checks %}
<h1>Exam:</h1>
<form action="{% url 'exam' %}" method="POST">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset.forms %}
<div class="form-group">
{{ form.checkbox }}
{{ form.text.value }}
{{ form.id }}
{{ form.text }}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% else %}
<h1>Results:</h1>
{% for check in checks %}
<p>{{ check.id }} {{ check.text }}</p>
{% endfor %}
{% endif %}

how to submit checklist in Django with GET

Hi I have on my html file this, tags and tagInfos are both queryset´s of Django, that 2 for´s are only to show wich one belongs to the other:
<form action="/chart/chart/" method="get">
{% if tags.count > 0 %}
{% for tag in tags %}
{% for tagInfo in tagInfos %}
{% if tag.taginfo_idtaginfo1_id == tagInfo.idtaginfo %}
<p>
<input type="checkbox" name="checks[]" value="{{ tag.idtag }}" />
</p>
{% endif %}
{% endfor %}
{% endfor %}
{% csrf_token %}
<button type="submit" class="btn btn-primary">Submit creation</button>
{% else %}
<p>None TAG to select.</p>
{% endif %}
</form>
So and on my view i try to do that:
def chart(request):
if 'checks' in request.GET and request.GET['checks']:
chosen = request.GET.getlist('checks')
return render_to_response('Chart/chart.html',{'chosen':chosen})
else:
return render_to_response('Chart/chart.html',{})
But don´t show any of the selected checkboxes on the other html, I´m using {{ chosen }} to show.
Any ideas of what I´m doing wrong?
try this:
def chart(request):
if 'checks[]' in request.GET: #<----- 'checks[]'
chosen = request.GET.getlist('checks[]') #<----- 'checks[]'
return render_to_response('Chart/chart.html',{'chosen':chosen})
else:
return render_to_response('Chart/chart.html',{})

Django forms adding <div> after form field

Below is my form code :
class FMessage(forms.Form):
From = forms.CharField()
To = forms.CharField()
Subject = forms.CharField()
Message = forms.CharField()
and this is my html code:
<form method='POST' action='.'>
{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='submit'>
</form>
The code works fine by displaying forms and has not any issue in functionality, but now I need to wrap my form fields in html by a div like this:
<div id='mydiv'>
<input ... />
<div>
How can I fix it?
Seems like you do not really want to use the inbuilt <p> or <table> wrapped forms and rather want to display the fields wrapped within a <div>'s. You can simply iterate over fields in the form as follows.
{% if form %}
<!-- Form Errors -->
{% if form.errors %}
<ul class="errors">
{% for error in form.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<!-- Display Form -->
<form>
{% csrf_token %}
{% for field in form %}
<div class="mydiv">
<label class="mylabel">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}
</form>
{% endif %}
Dont render the form by using form.as_p. You need to show each field of the form, for example, by using form.to. By using this way, you can wrap the field 'to' into a div
<div>{{ form.To}} </div>
For more detail, view this link

Categories