can not call function into wtforms radio field - python-3.x

I am trying to call a regular function into RadioField - choices[()].
when i select a radio button on my web page and click submit button, i should get the result from from function. my function says to print("Hi").
currently it print's the data on given value like 'value_one' when i select description.
So, i need a way to do call function to choices[('')].
below is my code
from flask import Flask, render_template
from flask_wtf import Form
from wtforms import RadioField, SubmitField
app = Flask(__name__)
app.config.from_object(__name__)
app.secret_key = 'password'
def print_1():
print("Hi")
class SimpleForm(Form):
example = RadioField('Label', choices=[('value_one','description'),('value_two','whatever')])
#app.route('/',methods=['post','get'])
def hello_world():
form = SimpleForm()
if form.validate_on_submit():
print(form.example.data)
else:
print(form.errors)
return render_template('form.html',form=form)
if __name__ == '__main__':
app.run(debug=True)
Below is my html code:
<form method="post">
{{ form.hidden_tag() }}
{{ form.example }}
<input type="submit" value="submit">
</form>

Related

How to stop Flask method from executing after hitting Page Reload

I have a basic HTML Form with file input that accepts multiple files. When the user clicks on Upload button I want to print numbers till 10**9 on my terminal.Say while execution of loop the user clicks refresh/reload, I want to stop current loop and redirect to index page. But even after hitting refresh the loop continues to execute.
index.html
<form method="POST" action="upload" enctype="multipart/form-data" class="uploader">
<input id="file-upload" type="file" name="fileUpload" accept=".ent,.pdb" multiple/>
<input type="submit" class="btn btn-primary" value="Upload"/>
</form>
app.py
from flask import Flask, render_template, redirect
UPLOAD_FOLDER = 'uploads'
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route("/")
def index():
return render_template("index.html")
#app.route('/upload',methods = ['GET','POST'])
def upload_file():
t=0
while(t<10**9):
print(t)
t+=1
return redirect('/')
if __name__ == '__main__':
app.run(debug=True)

Why is my function not printing anything in the CLI?

At the moment I am just trying to get the function to print what it has found in
the database, however I am not getting anything in the CLI when submitting
eywords via a form which has this functions URL as an action.
import os
from flask import Flask, render_template, redirect, request, url_for
from flask_pymongo import PyMongo
from bson.objectid import ObjectId
app = Flask(__name__)
app.config["MONGO_DBNAME"] = 'recipe_site'
app.config["MONGO_URI"] = os.getenv("MONGO_URI")
mongo = PyMongo(app)
#function for search bar.
#app.route('/search', methods=['GET', 'POST'])
def search():
mongo.db.recipes.create_index( { "name": "text" } )
if request.method == "POST":
q = request.form['search']
else:
q = ""
query = ( { "$text": { "$search": q } } )
results = mongo.db.recipes.find(query)
return render_template('searchresults.html', recipes = results)
The form that calls search function and captures key search word:
<form action="{{ url_for('search', text=text) }}" method="POST">
<div>
<div class="input-field">
<input id="search" name="search" type="text" class="validate">
<span class="helper-text" data-error="Try again" data-success="Done"></span>
</div>
</div>
<button type="submit">Submit </button>
</form>
Error code
Debugger PIN: 272-267-243
10.240.1.220 - - [25/May/2019 19:24:14] "POST /search/ HTTP/1.1" 404 -
As the code stands now all I expect is that it should print any collections in my database which have the keyword searched using the form.
You need to read the key words received from the post request using request.form['search']
like below:
#function for search bar.
#app.route('/search', methods=['GET', 'POST'])
def search():
# index for field name
mongo.db.recipes.create_index('name')
# index for field name and example
#mongo.db.recipes.create_index([("name", pymongo.DESCENDING),
#("example", pymongo.ASCENDING)])
if request.method == "POST":
q=request.form['search']
else:
q = ""
query = ( { "$text": { "$search": q } } )
results = mongo.db.recipes.find(query)
print (results)
return render_template('searchresults.html', recipes = results)
In the form, you need to replace
<form action="{{ url_for('search', text=text) }}" method="POST">
By
<form action="{{ url_for('search') }}" method="POST">
Edit:
I suggest to use GET method instead of POST for search feature because when the client refresh the browser, it ask him to confirm Form submission. So we need to replace:
if request.method == "POST":
q=request.form['search']
else:
q = ""
By
q = request.args.get('search', "")
And
<form action="{{ url_for('search') }}" method="POST">
by
<form action="{{ url_for('search') }}" method="GET">
Using the official documentation for PyMongo
Here is a tested code that might help.
from flask import Flask
from flask_pymongo import PyMongo
import pymongo
app = Flask(__name__)
app.config["MONGO_DBNAME"] = 'test'
app.config["MONGO_URI"] = "mongodb+srv://<username>:<password>#cluster0-vhd1j.gcp.mongodb.net/test?retryWrites=true"
mongo = PyMongo(app)
# mongo.db.collection.create_index([("name", pymongo.ASCENDING),("text", pymongo.ASCENDING)])
mongo.db.collection.insert_one({"name":"myname","text":"abcd"})
query = { "text": "abcd"}
results = mongo.db.collection.find(query)
for result in results:
print(result)
you can manipulate it as per your requirement. :)
I hope it helps.
Thank you for your attempts to support but I have now rectified the issue. The reason why nothing was printing in the cli was due the there being an issue with the create_index line. There was an existing index within that collection i was unaware of which was preventing this line from running.

Field validation in WTF Forms Flask, redirect method

I am trying to create my first Flask web application and found the following problem, I have two pages, the first page should take players names and give the names to the next page, but unfortunately name validation does not work due to some reason, I can keep the required fields empty and go to next page with empty names fields.
Flask code:
class ChooseName(FlaskForm):
first_player_name = StringField("Choose first player name: ", [DataRequired()])
second_player_name = StringField("Choose second player name: ", [DataRequired()])
button = SubmitField("Confirm")
#app.route('/')
def index():
form = ChooseName()
if form.validate_on_submit():
return redirect(url_for('mega'))
return render_template('TIC_TAC_TOE_index.html', form=form)
#app.route('/game_page', methods=["GET", "POST"])
def mega():
player1 = request.args.get('first_player_name')
player2 = request.args.get('second_player_name')
......
return render_template('mega.html', form=form, error=error, x=x,
turn=turn,tornado=tornado, renew=renew, player1=player1,player2=player2)
HTML template:
<form action="{{url_for('mega')}}" method="get">
{{ form.hidden_tag() }}
<h4>Please choose players names!</h4>
{{form.first_player_name.label}} {{form.first_player_name}} <br> <br>
{{form.second_player_name.label}} {{form.second_player_name}} <br> <br>
{{form.button}} <br> <br>
</form>
Well looking at your function Mega(), you're not returning anything on the next page. You're just accepting the input but aren't returning it in any form.
from wtforms import Form, StringField, validators, SubmitField
from flask_wtf import FlaskForm
from flask import Flask, render_template, request
class ChooseName(FlaskForm):
first_player_name = StringField("Choose first player name: ", [validators.DataRequired()])
second_player_name = StringField("Choose second player name: ", [validators.DataRequired()])
button = SubmitField("Confirm")
app = Flask(__name__)
app.config['SECRET_KEY'] = "IT_IS_SECRET"
#app.route('/')
def index():
form = ChooseName()
if form.validate_on_submit():
return redirect(url_for('mega'))
return render_template('TIC_TAC_TOE_index.html', form=form)
#app.route('/game_page', methods=["GET", "POST"])
def mega():
player1 = request.args.get('first_player_name')
player2 = request.args.get('second_player_name')
return player1 + ' ' + player2
if __name__ == '__main__':
app.run(port=5000,debug=True)
Try to run this code, I hope this helps. :-)
This is because your action is pointing to the mega view, so the code from index if form.validate_on_submit(): is not being executed.
You should change the action attribute and method in your form. The code should be as follows:
HTML template:
<form action="" method="post">
{{ form.hidden_tag() }}
<h4>Please choose players names!</h4>
{{form.first_player_name.label}} {{form.first_player_name}} <br> <br>
{{form.second_player_name.label}} {{form.second_player_name}} <br> <br>
{{form.button}} <br> <br>
</form>
Views:
from flask import session
#app.route('/')
def index():
form = ChooseName()
if form.validate_on_submit():
session['first_player_name'] = form.first_player_name.data
session['second_player_name'] = form.second_player_name.data
return redirect(url_for('mega'))
return render_template('TIC_TAC_TOE_index.html', form=form)
#app.route('/game_page', methods=["GET", "POST"])
def mega():
player1 = session.pop('first_player_name')
player2 = session.pop('second_player_name')
......
return render_template('mega.html', form=form, error=error, x=x,
turn=turn,tornado=tornado, renew=renew, player1=player1,player2=player2)
You can learn more about WTForms here https://j2logo.com/tutorial-flask-leccion-3-formularios-wtforms/

Django: ValueError at/ "The view To_do_list_app.views.home didn't return an HttpResponse object. It returned None instead."

Please, I am a newbie, if I didn't ask my question well, let me know.
I am working on a To-Do List app.
Anytime, I add a new task and time to the form on my web app and submit, I get the following error:
ValueError at /
The view To_do_list_app.views.home didn't return an HttpResponse object. It returned None instead.
Below is my views.py file
from django.http import HttpResponse
from django.shortcuts import render,redirect
from .forms import ListForm
from .models import List
def home(request):
if request.method == "POST":
form = ListForm(request.POST or None )
if form.is_valid():
form.save()
act = List.objects.all
context = {
"act":act
}
return render(request,"home.html",context)
else:
act = List.objects.all
context = {
"act":act
}
return render(request,"home.html",context)
Here is also my forms.py file
from django import forms
from .models import List
class ListForm(forms.ModelForm):
class Meta:
model = List
fields = "__all__"
here is my models.py file
from django.db import models
class List(models.Model):
activity = models.CharField(max_length=200,primary_key=True)
completed = models.BooleanField(default=False)
time = models.DateTimeField()
def __str__(self):
return self.activity
This is the home.html script(only the form html tag)
<form class="form-inline my-2 my-lg-0" method="POST">
{% csrf_token %}
<input class="form-control mr-sm-2" type="text" placeholder="Add New
Task" name="activity">
<input type = "datetime-local" name = "time" >
<button class = "btn btn-primary my-2 my-sm-0" type="submit">Add New Task</button>
</form>
I've fully integrated your code to my environment, carefully went trough your code and tested a few things. If you change the code of your views.py to the following, I think it will fix your problem:
from django.shortcuts import render
from .forms import ListForm
from .models import List
def index(request):
act = ''
if request.method == "POST":
form = ListForm(request.POST or None)
if form.is_valid():
form.save()
act = List.objects.all
return render(request, 'myApp/home.html', {"act": act})
else:
act = List.objects.all
return render(request, 'myApp/home.html', {"act": act})
resume: ( You had to make a global variable in the index-method ( or home method ) and set it to an empty string. Also you don't really need to use the context variable, you also can do it in the inline way, it will cost you less code. And last but not least you had to outdent the last return one time because that is the real return of the method. Otherwise the method only gives an if-structure with a return.. )

How do I save file in different directory upon clicking submit using flask?

I have a simple python file that sends a file from a local directory to be displayed in html. And, when the user clicks submit, I want to save this file to a different directory, but I can't seem to make this happen.
Here's my code:
Uploader.py
from __future__ import print_function
from random import choice
from flask import Flask, request, redirect, url_for, flash, render_template, abort, send_file, session
from werkzeug.utils import secure_filename
from flask import send_from_directory
import sys, os
app = Flask(__name__)
#app.route('/')
def init(file_Idx=0):
files = os.listdir(DOWNLOAD_FOLDER)
filePath = os.path.join(DOWNLOAD_FOLDER, files[file_Idx])
return render_template('files.html', file=filePath)
#app.route('/upload', methods=['POST'])
def upload_file():
file = request.files['image'] #Failing here!!!
f = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
file.save(f)
return render_template('files.html')
files.html
<form action="/upload" method="post" enctype="multipart/form-data">
<img src="{{file}}"/>
<input type=submit name="image">
</form>
Right now the image is displaying, but I can't seem to pass the file to upload_file() to save it in the upload_folder. How can I make this work?
Try this, you can define your desired path in it.
You can Edit the line
file.save(os.path.join("/tmp/", filename))
and place your desired path in it.
from flask import Flask, render_template, request
from werkzeug import secure_filename
app = Flask(__name__)
#app.route('/upload')
def upload_file():
return render_template('upload.html')
#app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join("/tmp/", filename))
if __name__ == '__main__':
app.run(debug = True)
and HTML code for that
<form id="package_form" action="" method="POST">
<div>
<p>Upload Packages:</p>
<p><input id="upload_button" type="file" class="btn btn-default btn-xs" name="file"></p>
<p><input id="submit_button" type="submit" class="btn btn-success" value="Upload">
</div>

Resources