**How To get All Data in a wtf form with a single command in a dictionary or list without needing to write this much lines of code, specifing every single element in the form and geting data seperately
**
#app.route('/add', methods=['POST', 'GET'])
def add_cafe():
form = CafeForm()
if form.validate_on_submit():
print("True")
cafe_name = form.cafe_name.data
cafe_location = form.cafe_location.data
opening_time = form.opening_time.data
closing_time = form.closing_time.data
coffee_rating = form.coffee_rating.data
wifi_strength_rating = form.wifi_strength_rating.data
power_socket_availability = form.power_socket_availability.data
return render_template('add.html', form=form)
The wtforms documentation says that that's Form.data:
A dict containing the data for each field.
In other words,
#app.route('/add', methods=['POST', 'GET'])
def add_cafe():
form = CafeForm()
if form.validate_on_submit():
data = form.data
print("True", data)
# ...
return render_template('add.html', form=form)
Related
The app has worked before, but it has been a while. It requests data from the user that gets sent to a machine learning model. The page should be the same with the results posted at the bottom of html page.
app = Flask(__name__, template_folder='templates')
with open(f'model/model.pkl', 'rb') as file:
model = pickle.load(file)
#app.route('/', methods=['GET', 'POST'])
def main():
if request.method == 'GET':
return(render_template('index.html'))
if request.method == 'POST':
input_list = request.form.to_dict()
input_list = list(input_list.values())
input_list = list(map(int, input_list))
result = Predictor(input_list)
if int(result)==1:
prediction='High'
else:
prediction='Low'
return render_template("index.html",prediction_text = 'Thank you for submitting your details. Your credit risk is : {}'.format(prediction))
def Predictor(input_list):
to_predict = np.array(input_list).reshape(1,15)
result = model.predict(to_predict)
return result[0]
I've tried making two templates of the same html form, where one holds the submit button and the other displays the result.
I have two views. One which is called gameReportRoster, and the other gameReportStats.
The basic flow of the views is as follows:
gameReportRoster receives a PK from another view. It then renders some forms and processed some data to get a list of the players who played in the game, as well as players who are being added to the roster.
When the user hits submit, some business logic is completed with some data stored to a temporary Model. At this point, we then need to call the gameReportStats to render the next set of forms. When calling gameReportStats, we need to pass to it one variable called game.
The issue I am facing is that when we call gameReportStats, the URL is not changing. So the Post Request is getting handled in gameReportRoster, although we should now be in gameReportStats.
def gameReportRoster(request, pk):
#login_required(login_url="/login/")
def gameReportRoster(request, pk):
**QUERIES AND FORM RENDERING HERE**
if request.method == 'POST':
if 'submitRoster' in request.POST:
print('submitRoster Was Pressed')
homePlayedList = request.POST.getlist('homePlayed')
awayPlayedList = request.POST.getlist('awayPlayed')
formsetHome = PlayerFormSet(data=request.POST, prefix='home')
formsetAway = PlayerFormSet(request.POST, prefix='away')
**OMMITED FORM PROCESSING DONE HERE FOR READABILITY**
tempGameResult = TempGameResults(game=game)
tempGameResult.save()
tempGameResult.homePlayers.set(homePlayersPlayed)
tempGameResult.awayPlayers.set(awayPlayersPlayed)
return gameReportStats(request, game)
**MORE QUERIES AND FORM RENDERING HERE**
return render(request, "home/game-report-roster.html", context)
def gameReportStats(request, game):
#login_required(login_url="/login/")
def gameReportStats(request, game):
tempGameResult = TempGameResults.objects.get(game=game)
# teams = Team.objects.filter(id__in=teamList)
homeTeam = Team.objects.get(id=game.homeTeam_id)
awayTeam = Team.objects.get(id=game.awayTeam_id)
teamList = [homeTeam.id, awayTeam.id]
teams = Team.objects.filter(id__in=teamList)
homePlayersPlayed = Player.objects.filter(id__in=tempGameResult.homePlayers.values_list('id'))
awayPlayersPlayed = Player.objects.filter(id__in=tempGameResult.awayPlayers.values_list('id'))
gameResultForm = GameResultForm(teams=teams)
formsetGoalHome = GoalFormSet(
queryset=Goal.objects.none(),
form_kwargs={'players': homePlayersPlayed},
prefix='goalHome'
)
formsetGoalAway = GoalFormSet(
queryset=Goal.objects.none(),
form_kwargs={'players': awayPlayersPlayed},
prefix='goalAway'
)
formsetPenaltyHome = PenaltyFormSet(
queryset=Penalty.objects.none(),
form_kwargs={'players': homePlayersPlayed},
prefix='penaltyHome'
)
formsetPenaltyAway = PenaltyFormSet(
queryset=Penalty.objects.none(),
form_kwargs={'players': awayPlayersPlayed},
prefix='penaltyAway'
)
context = {
'formsetGoalHome': formsetGoalHome,
'formsetPenaltyHome': formsetPenaltyHome,
'formsetGoalAway': formsetGoalAway,
'formsetPenaltyAway': formsetPenaltyAway,
'gameResultForm': gameResultForm,
'homeTeam': homeTeam,
'awayTeam': awayTeam,
}
** THIS IF NEVER GETS CALLED **
if request.method == 'POST':
print('Test')
** TEMPLATE GETS PROPERLY RENDERED, BUT URL NEVER CHANGES **
return render(request, "home/game-report-stats.html", context)
urls.py
path('game-report-roster/<str:pk>', views.gameReportRoster, name="gameReportRoster"),
path('game-report-stats/', views.gameReportStats, name="gameReportStats"),
what the actual URL looks like
http://127.0.0.1:8000/game-report-roster/fc4cd6db-d7f9-43b3-aa80-f9d4abfff0e5
Maybe instead of
return gameReportStats(request, game)
try:
return redirect('myappname:your_name_in_urls.py', game)
I've been building a webapp for the HR department which will (hopefully) include the ability for staff to submit timesheets and I have become stuck when trying to submit a timesheet. The connection string is working as I can see other data from the database. I have been working through errors but this 07002 error is one I can't work out what is causing it.
I've tried two different ways to get this working. Here is the first attempt in my app.py file -
#app.route('/timesheet', methods=['GET', 'POST'])
def employee_timesheet():
if request.method == "POST":
employee_id = request.form['employee_id']
department = request.form['department']
mondaystart = request.form['mondaystart']
mondayend = request.form['mondayend']
tuesdaystart = request.form['tuesdaystart']
tuesdayend = request.form['tuesdayend']
wednesdaystart = request.form['wednesdaystart']
wednesdayend = request.form['wednesdayend']
thursdaystart = request.form['thursdaystart']
thursdayend = request.form['thursdayend']
fridaystart = request.form['fridaystart']
fridayend = request.form['fridayend']
saturdaystart = request.form['saturdaystart']
saturdayend = request.form['saturdayend']
result = request.form
cursor = cnxn.cursor()
cursor.execute('''INSERT INTO dbo.submitted_timesheet (employee_id, department, mondaystart, mondayend, tuesdaystart, tuesdayend, wednesdaystart, wednesdayend, thursdaystart, thursdayend, fridaystart, fridayend, saturdaystart, saturdayend,) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)''')
cnxn.commit()
flash("Your form was successfully submitted")
print("Form data submitted")
return redirect (url_for('success.html', result=result))
return render_template("staff_timesheets.html")
The other way then is -
#app.route('/timesheet', methods=['GET', 'POST'])
def employee_timesheet():
if request.method == "POST":
employee_id = request.form['employee_id']
department = request.form['department']
mondaystart = request.form['mondaystart']
mondayend = request.form['mondayend']
tuesdaystart = request.form['tuesdaystart']
tuesdayend = request.form['tuesdayend']
wednesdaystart = request.form['wednesdaystart']
wednesdayend = request.form['wednesdayend']
thursdaystart = request.form['thursdaystart']
thursdayend = request.form['thursdayend']
fridaystart = request.form['fridaystart']
fridayend = request.form['fridayend']
saturdaystart = request.form['saturdaystart']
saturdayend = request.form['saturdayend']
insert_query = '''INSERT INTO submitted_timesheet (employee_id, department, mondaystart, mondayend, tuesdaystart, tuesdayend, wednesdaystart, wednesdayend, thursdaystart, thursdayend, fridaystart, fridayend, saturdaystart, saturdayend,) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)'''
result = request.form
cursor = cnxn.cursor()
cursor.execute(insert_query, values)
cnxn.commit()
flash("Your form was successfully submitted")
print("Form data submitted")
return redirect (url_for('success.html', result=result))
return render_template("staff_timesheets.html")
If I submit a timesheet, I get the Pyodbc error in the title. Everything matches up in terms of column names and types. The HTML form should be fine too but can post it if needed for context.
Any ideas where I am going wrong?
Thank you!
I am having trouble validating a dynamically generated WTForms SelectField. Somehow my self.choices is empty during POST while they are populated on the first GET request. Am I missing something?
app.py:
#app.route('/users/edit/<email>/', methods=['GET', 'POST'])
def users_edit(email):
match = False
for user in session['users']['message']:
if user['email']['S'] == email:
match = True
if match:
form = EditUserForm()
if request.method == 'GET':
form_data = session.get('edit_user_form_data', None)
if form_data:
form = EditUserForm(MultiDict(form_data))
form.shops_allowed.choices = [(str(shop['shop_id']['S']), str(shop['general']['M']['shop_name']['S'])) for i, shop in enumerate(session['shops']['message'])]
print(f"SHOPS_ALLOWED CHOICES WITH FORM DATA: {form.shops_allowed.choices}")
form.validate()
session.pop('edit_user_form_data', None)
else:
form.email.data = email
form.shops_allowed.choices = [(str(shop['shop_id']['S']), str(shop['general']['M']['shop_name']['S'])) for i, shop in enumerate(session['shops']['message'])]
print(f"SHOPS_ALLOWED CHOICES WITHOUT FORM DATA: {form.shops_allowed.choices}")
matched_shop = []
for user in session['users']['message']:
if user['email']['S'] == email and 'shops_allowed' in user.keys():
matched_shop = [allow['S'] for allow, shop in zip(user['shops_allowed']['L'], session['shops']['message'])]
form.shops_allowed.data = matched_shop
form.validate()
if request.method == 'POST' and form.validate_on_submit():
app.logger.info(f"PRE POST EDIT USER FORM DATA: {form.data}")
url = ...
<REDACTED POST REQUESTS ENDPOINT>
app.logger.info(f"POST EDIT USER RESPONSE: ({post_response.status_code}) {response_data}")
if post_response.status_code == 200:
session.pop('edit_user_form_data', None)
return redirect(url_for('users'))
else:
app.logger.info(f"EDIT USER FORM DATA: {form.data}")
session['edit_user_form_data'] = form.data
return redirect(url_for('users_edit', email=email))
elif request.method == 'POST' and form.validate_on_submit() == False:
app.logger.info(f"EDIT USER FORM DATA VALIDATION FAILED: {form.data}")
session['edit_user_form_data'] = form.data
return redirect(url_for('users_edit', email=email))
forms.py
class NonValidatingSelectMultipleField(SelectMultipleField):
def __len__(self):
return 1
def pre_validate(self, form):
pass
# HACK TO VALID A CHOICE FOR SELECT MULTIPLE
if self.data:
print(f"SELF DATA: {self.data}")
print(f"VALUES: {self.choices}")
values = list(self.coerce(c[0]) for c in self.choices)
print(f"PROCESSED VALUES: {values}")
for d in self.data:
if d not in values:
raise ValueError(self.gettext("'%(value)s' is not a valid choice for this multiple select field") % dict(value=d))
class EditUserForm(FlaskForm):
email = StringField('Email', [
validators.DataRequired(),
validators.Length(min=6),
validators.Email(message='Not a valid email address.')]
)
shops_allowed = NonValidatingSelectMultipleField(
'Shops',
widget = widgets.ListWidget(prefix_label=False),
option_widget = widgets.CheckboxInput(),
coerce=str
)
This renders the following logging:
SHOPS_ALLOWED CHOICES WITHOUT FORM DATA: [('decb5a00-fe45-484f-b887-b9bd41c4f0f2', 'My shop'), ('2cea2efa-7ccf-4bca-896d-16119d5fb7a8', 'My other shop')]
SELF DATA: ['decb5a00-fe45-484f-b887-b9bd41c4f0f2', '2cea2efa-7ccf-4bca-896d-16119d5fb7a8']
VALUES: [('decb5a00-fe45-484f-b887-b9bd41c4f0f2', 'My shop'), ('2cea2efa-7ccf-4bca-896d-16119d5fb7a8', 'My other shop')]
PROCESSED VALUES: ['decb5a00-fe45-484f-b887-b9bd41c4f0f2', '2cea2efa-7ccf-4bca-896d-16119d5fb7a8']
127.0.0.1 - - [03/Apr/2020 14:30:11] "GET /users/edit/my#email.com/ HTTP/1.1" 200 -
After POST:
SELF DATA: ['decb5a00-fe45-484f-b887-b9bd41c4f0f2', '2cea2efa-7ccf-4bca-896d-16119d5fb7a8']
VALUES: None
And on screen:
forms.py", line 35, in pre_validate values = list(self.coerce(c[0]) for c in self.choices) TypeError: 'NoneType' object is not iterable
Meh, after going over my code once more I finally found the issue. I am calling form.validate_on_submit() at the same time I am verifying if request.method == 'POST' which never gives me the possibility to populated the choices during POST.
Changed my code to be:
if request.method == 'POST':
form.shops_allowed.choices = [(str(shop['shop_id']['S']), str(shop['general']['M']['shop_name']['S'])) for i, shop in enumerate(session['shops']['message'])]
form.validate_on_submit()
And it started to work. Sometimes you just need to write things down to see the answer :-)
I have in my controller default.py:
def images():
record = db.images(request.args(0))
form = SQLFORM(db.images, record, deletable=True,
upload=URL('download'), fields=['image'])
if request.vars.image!=None:
# form.vars.image_filename = request.vars.image.filename
form.vars.image_filename = "picture_spark_"+str(auth.user.id)
# form.vars.image_filename = "default"
if form.process().accepted:
response.flash = 'form accepted'
elif form.errors:
response.flash = 'form has errors'
return form
def dashboard():
return dict(img_upload_form=images())
In my view dashboard.html, I use the form like this:
{{=img_upload_form}}
However, the problem is that it doesn't work. I choose an image but after I click Submit, there is no change.
Any help is appreciated!
To solve this problem,
I added a print record line to my default.py controller.
What I observed was that the output was None.
My URL is http://127.0.0.1:8000/Spark/default/home. In essence, home.html does an AJAX call to dashboard.html.
Now, in my controller, I defined it as follows:
def dashboard():
return dict(img_upload_form=images())
What I needed to do was return the same form for home.html
def home():
return dict(img_upload_form=images())
This allowed me to successfully upload images!