python3 flask: how to display the json result in html - python-3.x

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:

Related

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 to resolve NoReverseMatch Exception for 'app_list' with upload files in changelist view page of model admin using django 3?

Code snippets that I was able to add so far:
Model class:
class MboxForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MboxForm, self).__init__(*args, **kwargs)
csv_file = forms.FileField(required=True,
label="Select CSV file")
class Meta:
model = Mbox
fields = ['some_field',
]
widgets = {
'csv_file': forms.FileInput(),
}
In admin.py:
class MboxAdmin(admin.ModelAdmin):
actions = [import_from_csv,
export_to_csv]
def get_form(self, request, obj=None, **kwargs):
kwargs['form'] = MboxForm
return super().get_form(request, obj, **kwargs)
def get_urls(self):
urls = super().get_urls()
my_urls = [
path("upload_csv",
self.upload_csv, name='upload_csv')
]
return my_urls + urls
urls = property(get_urls)
def upload_csv(self, request):
if request.method == 'POST':
form = MboxForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('admin/change_list.html')
else :
return render(request, 'admin/change_list.html',
{'form': form,
'opts': Mbox._meta})
else:
return render(
request,
'admin/change_list.html',
context
)
def changelist_view(self, request, extra_context=None):
extra_context = {}
extra_context['submit_csv_form'] = MboxForm
if 'action' in request.POST and request.POST['action'] == 'import_from_csv':
if not request.POST.getlist(admin.ACTION_CHECKBOX_NAME):
post = request.POST.copy()
for u in Mbox.objects.all():
post.update({admin.ACTION_CHECKBOX_NAME: str(u.id)})
request._set_post(post)
return super().changelist_view(request, extra_context=extra_context)
This button displays in place of the add button in the listing page with the template with the file browser to upload any file.
{% extends "admin/change_list.html" %}
{% load i18n admin_urls static admin_list %}
{% block object-tools %}
{% if has_add_permission %}
{% block object-tools-items %}
<form id="upload-csv-form" method="POST"
action="{% url 'admin:upload_csv' %}"
method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
{% comment %}
<p>{{ submit_csv_form.as_p }}</p>
{% endcomment %}
<p>{{ submit_csv_form.csv_file.errors }}</p>
<p><input type="file" value="CSV file" />
<p><input type="submit" value="Upload" />
<!-- input type="reset" value="Reset"> -->
</form>
{% endblock %}
</ul>
</div>
{% endif %}
{% endblock %}
The error That I get on clicking the upload button:
NoReverseMatch
Exception Value:
Reverse for 'app_list' with keyword arguments '{'app_label': ''}' not
found. 1 pattern(s) tried: ['admin/(?P<app_label>auth|mailmanager)/$'
mailmanager is the app for which the model: Mbox exists. Besides where do I place this change_view.html template in the template structure for only this model. I tried placing the template under myproject/templates/admin/templates/mailmanager/mbox, but it is not found. Also I don't wish to replace the 'Add model' button but have this placed next to it in the default model change list template.
I have followed the stack link so far but not got it working as yet. :Upload CSV file in django admin list view, replacing add object button Please guide .

Submitting a HTML form in Flask creates error with request.form

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

Flask - prevent function from reloading?

I am not sure how to explain the issue, but I am trying to get flask to load my main() function once, and then stay "within" that function as the user clicks buttons.
I have a list of image names (e.g. 20190101.jpg, 20190111.jpg, 20190323.jpg) that are baiscally in YYYYMMDD.jpg format.
When I first load my site, I want it to show all images. However, I have also added a Calendar Picker that allows the user to select a date, and on the date selection, my routes.py looks for images in that range only, and returns those for view.
I can do this part, no problem. The issue is when the users click the "next photo"/"previous photo"/"random" button, or select an image from my table list. When they do that, the default photo list loads, instead of the filtered one.
As I have it, I understand that's because main() is getting called on the button click, and I have _images = image_urls at the very top, so it is effectively resetting the list.
How can I write my function(s) to load _images = image_urls ONCE, and then keep that list and update only as the user tells it to?
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
<link rel="stylesheet" type="text/css" href= "{{ url_for('static',filename='styles/index.css') }}">
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
</head>
<body>
{% extends "layout.html" %}
{% block content %}
<h3>Index: {{ photo_index }}</h3>
<h3>Filename: {{ image }}</h3>
{% include "/HTML Snippets/calendar.html" %}
<div class='image-container' id='image'>
{% include "/HTML Snippets/favorite_button.html" %}
<img src="{{ url_for('images.static', filename=image) }} " id="the-photo">
</div>
<div class='button-container' id='buttons'>
<form action="" method="post">
<input type="hidden" name="prev-next-buttons">
<input type="submit" value="Prev photo" name='prev-photo'>
<input type="submit" value="Next photo" name='next-photo'>
<input type="submit" value="Random photo" name='random-photo'>
<br/>
<button type='button' id='rotate-button' onclick="rotateMeCounterClockwise('#the-photo')">Rotate Photo CounterClockwise</button>
<button type='button' id='rotate-button' onclick="rotateMeClockwise('#the-photo')">Rotate Photo Clockwise</button>
</form>
<h3>Choose image from list:</h3>
<form method="post">
<input type="hidden" name="photo-select">
<select name="select-image" onfocus='this.size=5;' onblur='this.size=1' onchange="this.size=1; this.blur(); this.form.submit()">
{% for eimage in image_list %}
<option
{% if eimage == image %}
selected
{% endif %}
value = {{ eimage }}
>
{{eimage}}
</option>
{% endfor %}
</select>
</form>
</div>
<div class='table-container'>
<table id='image-list' name='select-from-table'>
{% for image_row in image_list | batch(3) %}
<tr>
{% for image in image_row %}
<td> {{ image }} </td>
{% endfor %}
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
</body>
</html>
calendar.html
{% block topscripts %}
<link rel="stylesheet" type="text/css" href= "{{ url_for('static',filename='styles/calendar.css') }}">
<script>
$(function() {
$("#datepicker").datepicker();
});
</script>
{% endblock %}
{% block content %}
<form method="post">
<p>Date: <input type="text" id="datepicker" name='go-to-date'></p>
<input type="hidden" name="calendar-form">
<input type="submit">
</form>
{% endblock %}
{% block endscripts %}
{% endblock %}
routes.py
[imports and misc]
images = os.listdir(IMAGE_FOLDER)
def create_urls(files):
image_urls = []
for file in files:
if file.endswith(".jpg"):
image_urls.append(file)
return image_urls
image_urls = create_urls(images)
image_urls.append('favicon.ico')
# Subtract 2 below, so you don't include the
# favicon.ico
num_images = len(image_urls) - 2
class Photo_Index():
def __init__(self, index=0):
self.index = index
def increase_number(self):
if self.index == num_images:
self.index = 0
else:
self.index = self.index + 1
return self.index
def decrease_number(self):
if self.index == 0:
self.index = num_images
else:
self.index = self.index - 1
return self.index
def random_number(self):
self.index = random.randint(0, num_images)
return self.index
def set_number(self, number):
self.index = number
return self.index
...
def day_month_year(filename):
"""
Takes a string `20190212` and pulls out Year, Month, Date
"""
year = filename[:4]
month = filename[4:6]
day = filename[6:8]
return str(year + "-" + month + "-" + day)
def get_files_on(specific_date):
_files = []
print("\nLooking for files on:", specific_date, "\n")
for file in image_urls:
# print(file, day_month_year(file))
if day_month_year(file) == specific_date:
_files.append(file)
return _files
photo_index_obj = Photo_Index()
fav_photo_index = Photo_Index()
def update_index(rqst, indx_obj):
if 'prev-photo' in rqst.form:
indx_obj.decrease_number()
elif 'next-photo' in rqst.form:
indx_obj.increase_number()
elif 'random-photo' in rqst.form:
indx_obj.random_number()
return indx_obj
#app.route("/", methods=["GET", "POST"])
#app.route("/<chosen_image>", methods=["GET", "POST"])
def main(chosen_image=None):
_images = image_urls
if request.method == "POST":
if 'go-to-date' in request.form:
spec_date = request.form['go-to-date']
spec_date = datetime.datetime.strptime(spec_date, "%m/%d/%Y").strftime("%Y-%m-%d") # noqa
_images = get_files_on(spec_date)
elif 'prev-next-buttons' in request.form:
update_index(request, photo_index_obj)
elif 'photo-select' in request.form:
img = request.form.get("select-image")
photo_index_obj.set_number(_images.index(str(img)))
elif 'favorite-photo' in request.form:
add_to_favorites(_images[photo_index_obj.index])
elif 'un-favorite-photo' in request.form:
remove_from_favorites(_images[photo_index_obj.index])
if request.method == "GET":
if chosen_image is not None:
photo_index_obj.set_number(_images.index(chosen_image))
favorite = is_favorite(_images[photo_index_obj.index])
return render_template('index.html',
title="Local Image Viewer",
photo_index=photo_index_obj.index,
image=_images[photo_index_obj.index],
image_list=_images,
favorite=favorite)
(I tried to keep routes.py to show just the minimum required, but if you want to see any functions specifically, please let me know).
Here's an example of what I mean - on load, it shows all images. I can then choose a date, and the routes.py updates the _images list to include just those on that date (yay!). But when I click "next picture", instead of going to the next picture in the new _images, it reloads the images from image_urls. I understand that's because the first line in main() is _images = image_urls. (I'm learning Flask so I also understand my function is a little kludgy).
My question is how do I properly set these at first, but then after main is called the first time, use _images as set in the code?
What you ask for is quite similar to URL filters and pagination. Widespread practice (you can see it on most php-based blogs/e-shops/etc.) is when you click on a date, you apply a date filter, so your front-end makes a request like GET localhost?date=1.1.2019 and your flask app should extract that date and return images based on that filter. By default, first image of that list should be returned and when you click a next photo button, you make a request like GET localhost?date=1.1.2019&offset=2. Offset means that you need a second image (or page) from the all filtered results.

If else in django template

I have a problem with if/else condition into my template.
I have a simple form and confirmation button. User should input text in this form, then should press button and only after that, user will see other part of page.
This is my template code:
{% extends "home/base.html" %}
{% load staticfiles %}
{{% block body %}
<h1 align="center">Analyzed text</h1>
<form class="form" action="analyze" method="post">
<div id="form">
<dd><textarea id="textarea" name="q" rows=10 cols=55 placeholder=" Input your text in japanese here ..."></textarea>
<dd><input class="myButton" type="submit" value="Analyze">
</div>
</form>
<div class=page>
{% if 'q' != None %}
{% include "kanji_analyzer/show_results.html" %}
{% endif %}
</div>
{% endblock %}}
views.py
from django.shortcuts import render_to_response
from kanji_analyzer.logic_part.kanji_analyzer import KanjiesText
def start_kanji(request):
return render_to_response('kanji_analyzer/main.html')
def show_entries():
global analyzed_text
global list_of_percents
global list_of_find_kanjies
return render_to_response('show_entries.html', {'analyzed_text': analyzed_text, 'list_of_percents': list_of_percents,
'list_of_find_kanjies': list_of_find_kanjies,})
def send_text(request):
if 'q' in request.POST:
q = request.POST['q']
a = KanjiesText(request.POST['q'])
a.remove_spaces_from_text()
list_of_percents = a.take_percent_count()
list_of_find_kanjies = a.list_find_kanjies()
for i in range(0,5):
if len(list_of_find_kanjies[i]) == 0:
list_of_find_kanjies[i] = ''
return render_to_response('kanji_analyzer/main.html', {'q': q, 'list_of_percents': list_of_percents,
'list_of_find_kanjies': list_of_find_kanjies,})
else:
q = "your form is empty"
return render_to_response('kanji_analyzer/main.html', {'q': q},)
This block if/else doesn't work. 'q' - value with user's text

Resources