Submitting a HTML form in Flask creates error with request.form - python-3.x

Hey I am new to Flask and am trying to make a basic quiz app,
#app.route('/answers', methods=['GET', 'POST'])
def answers():
correct = 0
incorrect = 0
total = correct + incorrect
if request.method == 'POST':
submitted_answer = request.form['answer']
if submitted_answer == question_option1:
correct += 1
new_result = Question(correct=correct, total=total)
db.session.add(new_result)
db.session.commit()
else:
incorrect += 1
new_result = Question(incorrect=incorrect, total=total)
db.session.add(new_result)
db.session.commit()
return redirect('/answers')
all_questions = Question.query.order_by().all()
return render_template('answers.html', questions=all_questions, correct=correct, incorrect=incorrect, total=total)
while the html code looks like this
{% extends 'base.html' %}
{% block body %}
<p1>
<list>
{% for question in questions %}
<h2>{{ question.text }}</h2>
<input type="radio" name="answer" value="option1"> {{ question.option1 }} <br>
<input type="radio" name="answer" value="option2"> {{ question.option2 }} <br>
<input type="radio" name="answer" value="option3"> {{ question.option3 }} <br>
<input type="radio" name="answer" value="option4"> {{ question.option4 }} <br>
{% endfor %}
</list>
<form action='/answers' method='POST'>
<input type="submit" name="submitted" value="Check Scores">
</form>
<p1>You got a score of {{ correct }}/{{ total }}</p1>
</p1>
{% endblock %}
In a different part of my app I am able to get information from the HTML using the same method but in this case I keep getting the error
'werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'answer''
when I try to submit the checklist and can't work out why
I am new to programming so sorry if i'm missing something very basic but thanks for the help!

Your answer inputs need to be inside the form tag to be submitted - there is no 'answer' element in the form you are submitting

Related

Show image name inside the image field in Django forms

I have this edit or update form in which I want to display only the image name in the form for a better user experience so that the user could know which image he has uploaded while creating the data.
I am storing the image name in the model as well,but i want to display the image name inside the image field.
forms.py
class MenuCategoryForm(forms.ModelForm):
image = forms.ImageField(allow_empty_file=True, required=False)
class Meta:
model = MenuCategory
fields = ['name', 'description', 'menu_options']
view
def menu_category_update(request, id):
item = MenuCategory.objects.get(id=id)
if request.method == 'POST':
form = MenuCategoryForm(request.POST, request.FILES, instance=item)
if form.is_valid():
if request.FILES['image']:
image = request.FILES['image']
image_url = upload_image(image, 'menu_category', image.name)
obj = form.save(commit=False)
obj.image_url = image_url
form.save()
else:
form.save()
return redirect('menu-category')
else:
form = MenuCategoryForm(instance=item)
context = {
'form': form,
'item': item
}
return render(request, 'menu/menu_category_update.html', context)
Template
{% extends 'partials/base.html' %} {% load crispy_forms_filters %} {% load
crispy_forms_tags %}
<!-- {% block title %}Menu category {% endblock %} -->
{% block content %}
<div class="container edit-form-flex">
<div class="row Edit-form-box">
<div class="form-inner-box bg-white">
<div class="heading-editing">
<h3>Edit menu category</h3>
</div>
<form method="POST" class="add-new-form edit-form" enctype="multipart/form-data">
{% csrf_token %} {{ form|crispy }}
<div class="update-buttons-container">
<button class="btn btn-info1" type="submit" value="Update">
Update
</button>
<a class="btn btn-secondary" href="{% url 'menu-category' %}"
>Cancel</a
>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
Well in other to get the name of the image in your form you will be better off in using a form initial like so:
def menu_category_update(request,id):
item = MenuCategory.objects.get(id=id)
if request.method == 'POST':
form = MenuCategoryForm(request.POST, request.FILES, instance=item)
if form.is_valid:
obj = form.save(commit=False)
# obj.username = request.user
form.save()
return redirect('menu-category')
else:
form = MenuCategoryForm(
initial={'image':item.image,
'name':item.name,
'description':iteem.description,
})# this are the fields that we want to show in the form
context = {
'form': form,
'item': item
}
return render(request, 'menu/menu_category_update.html', context)
In your form html you will apply the form initial to the field that you want to show in your form, by doing something like this: form.initial.name As i have illustrated below :
{% extends 'partials/base.html' %} {% load crispy_forms_filters %} {% load
crispy_forms_tags %}
<!-- {% block title %}Menu category {% endblock %} -->
{% block content %}
<div class="container edit-form-flex">
<div class="row Edit-form-box">
<div class="form-inner-box bg-white">
<div class="heading-editing">
<h3>Edit menu category</h3>
</div>
<form method="POST" class="add-new-form edit-form" enctype="multipart/form-data">
{% csrf_token %}
<label> Image name </label>
{{form.initial.name}}
<label> Description </label>
{{ form.initial.description }}
<label> Image </label>
{{ form.initial.image }}
<div class="update-buttons-container">
<button class="btn btn-info1" type="submit" value="Update">
Update
</button>
<a class="btn btn-secondary" href="{% url 'menu-category' %}"
>Cancel</a
>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

django not displaying error_messages in forms

i am new to django and i have this form i am working on i have tried everything possible i cant seem to display the form error messages. i have tried using a def clean method nothing happens when i try to submit an empty form..i have tired switing to using FormView i have also tried using function view i have tried using a for loop and adding {{ form.non_field_errors }} in my template nothing pops up.
my app/forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField( label='Your Name', min_length=2, max_length=25, required=True, error_messages ={'required':'Please tell Oluwafemi your name'})
email = forms.EmailField(label='Your Email', required=True, error_messages={'invalid':'Please fill in a valid email'})
subject = forms.CharField(label='Subject', min_length=4, max_length=100, required=True)
message = forms.CharField(widget=forms.Textarea(attrs={'placeholder':'Write Oluwafemi a Message'}), error_messages ={'required':'Please write something for Oluwafemi'})
my app/views.py
from django.views.generic import TemplateView
from django.shortcuts import render
from django.core.mail import send_mail
from .forms import ContactForm
from django.http import HttpResponseRedirect
# Create your views here.
class ProfilePageView(TemplateView):
template_name = 'femi_profile.html'
form_class = ContactForm
success_url = 'femiir'
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
# Send the email
send_mail(
f"{subject} - message from {name} ", # message subject
message, # Message Body
email, # Sender's mail (From mail)
['d4rahl#gmail.com'], # Reciever's mail(To mail)
)
return HttpResponseRedirect('femiir')
return render(request, self.template_name, {'form': form})
snippet of my html template
<div class="col-lg-7 mt-5 mt-lg-0 d-flex align-items-stretch">
<form method="post">
{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-6">
{{ form.name|as_crispy_field }}
</div>
<div class="form-group col-md-6">
{{ form.email|as_crispy_field }}
</div>
</div>
<div class="form-group">
{{ form.subject|as_crispy_field }}
{{ form.message|as_crispy_field }}
</div>
<div class="text-center"><button type="submit" class="btn btn-primary ">Send Message</button></div>
</form>
</div>
please what i my doing wrong
Did you try looping through form.errors in template?
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
{{ error }}
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
{% endif %}
When you are rendering fields manually you would have to use error tags.
{{ form.name_of_field.errors }}
<form method="post">
{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-6">
{{ form.name|as_crispy_field }}
{{ form.name.errors}}
</div>
<div class="form-group col-md-6">
{{ form.email|as_crispy_field }}
{{ form.email.errors}}
</div>
</div>
<div class="form-group">
{{ form.subject|as_crispy_field }}
{{ form.subject.errors}}
{{ form.message|as_crispy_field }}
{{ form.message.errors}}
</div>
<div class="text-center"><button type="submit" class="btn btn-primary ">Send Message</button></div>
</form>
https://docs.djangoproject.com/en/dev/topics/forms/#rendering-fields-manually

Flask RadioField is not working in form POST

Can someone please help resolving RadioField Post issue in below code snippet
As below code is not moving form.validate_on_submit()
**forms.py**
class validatingSPLForm(FlaskForm):
srcfile = FileField('Select Source ZIP', validators=[FileRequired(), FileAllowed(['zip'], 'Only ZIP files are allowed')])
submit = SubmitField("Validate")
proceed = IntegerField()
SPLFiles = RadioField('SPL', choices=[])
archiveresult = []
**routes.py**
app.route('/validatingSPLForm', methods=['GET', 'POST'])
def validatingSPLForm():
form = validatingSPLForm()
if request.method == 'POST':
if form.validate_on_submit():
form.SPLFiles.choices = [(elem.name, elem.des) for elem in form.archiveresult]
**validatingSPLForm.html**
{% extends "layout.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="" enctype="multipart/form-data">
</form>
</div>
{% endblock content %}
{% block content1 %}
<div class="content-section">
<h6><b class="text-success">"{{ form.srcfile.data.filename }}"</b> is valid, select one of the below SPL for further validation </h6>
{{ form.SPLFiles() }}
</div>
{% endblock content1 %}

How can I read user inputs from a dynamically created form in flask?

I want to create a dynamic input form and read the user inputs back when a button ("Submit") is pressed, what is the best way (a good way) to do this?
I have tried creating a dynamic form with a FieldList but I was unable to get the values from the user.
This is (hopefully all of) the relevant code:
forms.py
class EntryForm(Form):
field = StringField()
class DynamicForm(FlaskForm):
parameter = FieldList(FormField(EntryForm), min_entries=1)
submit = SubmitField('Submit')
routes.py
#app.route("/new", method=['GET', 'POST'])
def new_form():
form = DynamicForm()
if form.validate_on_submit():
values = form.parameter #This does not work as intended.
do_stuff(values)
return redirect(url_for('index'))
parameter = utils.get_parameter()
return render_template('dynamic_form.html', form=form, parameter=parameter)
where utils.get_parameter() returns an unknown list of parameters. Or to be precise the function expects a parameter and returns a list based on this paramater, but I have omitted this here.
dynamic_form.html
{% extends "layout.html" %}
{% macro render_field(item) %}
<div class="form-group">
<label class="form-control-label">{{ item.label }}</label>
<input type="text" name="{{ item.name }}" class="form-control" value="{{ item.value }}"/>
</div>
{% endmacro %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class ="form-group">
<legend class="border-bottom mb-4">Parameter</legend>
{% for item in form.parameter %}
{{ render_field(item) }}}
{% endfor %}
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
{% endblock content %}
I assume it is because the validate_on_submit() is called after the form is constructed (again) and thus it does not contain the form fields, and especially not the user inputs. Is there a way to prevent this "data loss" or is this a completely wrong approach?
Also, please let me know if information is missing.
You don't want to validate the form when the page first loads. Try this first:
if request.method == "POST" and form.validate_on_submit():
values = form.parameter
do_stuff(values)
return redirect(url_for('index'))
Next, notice that you are redirecting them to your view for def index():. Is that what you want?

python3 flask: how to display the json result in html

Now I want to send the json data to html, I just display the dictionary data(json), How to display the value of dictionary in the html.
The python code is:
#app.route('/upload', methods=['GET', 'POST'])
def upload():
if request.method == 'POST':
img_file = request.files['img_file']
if img_file and allowed_file(img_file.filename):
filename = secure_filename(img_file.filename)
img_file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
raw_img_url = './static/asset/uploads/' + filename
result_img_url = './static/asset/output/Line/' + filename
ratio = check_banner(filename)
result_dict = {'result': ratio}
return render_template("upload.html", result_img_url=result_img_url, result=json.dumps(result_dict))
else:
return ''' ok</p> '''
else:
return redirect(url_for('upload'))
The html code:
{% extends "base.html" %}
{% block content %}
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" id="img_file" name="img_file" class="col-sm-4">
<input type="submit" value="check" class="btn">
</form>
<p>
{% if result_img_url %}
<img src="{{ result_img_url }}" width='400' height='350'>
{% endif %}
</p>
<ul>
<li>{{result}}</li>
</ul>
{% endblock %}
But the result html is, but I just want to show the value of result :
If you want to pass only one parameter in result, you may change result_dict = {'result': ratio} to result = ratio.
It will show only the result in the page:

Resources