I'm a bit confused as how to have a "Delete" button on a page that will delete the object currently in focus.
I'm trying to add this button to /edit/ to delete whichever id is open
Using Python3 and Flask
forms.py
class EditForm(Form):
name = StringField('Server Name', validators = [Length(1, 120), DataRequired()])
ip_address = StringField('IP Address', validators = [Length(1, 16), IPAddress()])
username = StringField('UCX User', validators = [Length(1, 64)])
password = StringField('UCX Password', validators = [Length(1, 64)])
description = StringField('Purpose/Description', validators = [Length(1-120)])
protocol = RadioField('Protocol', [DataRequired()],
choices=[('https', 'HTTPS'), ('http', 'HTTP')], default='https')
submit = SubmitField('Submit')
**delete = SubmitField('Delete')**
Routes.py
#servers.route('/edit/<id>', methods=['GET', 'POST'])
def edit(id):
server = UcxServer.query.filter_by(id=int(id)).first_or_404()
form = EditForm(obj=server)
if form.validate_on_submit():
form.to_model(server)
db.session.commit()
flash('Your changes have been saved.')
return render_template('addserver2.html', form=form)
Routes.py delete function:
#servers.route('/delete/<id>')
def delete(id):
server = UcxServer.query.filter_by(id=int(id)).first_or_404()
try:
db.session.delete(server)
db.session.commit()
flash('Successfully deleted the {} server'.format(server))
return redirect(url_for('servers.index'))
Template (addserver2.html):
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block page_content %}
<div class="page-header">
<h1>UCX Server</h1>
</div>
{{ wtf.quick_form(form) }}
{% endblock %}
So basically, I can load the edit/ page, but how do I hook up the "Delete" SubmitField to call the /delete/?
Figured it out. Posting answer for future folks.
Not sure if best way, but only took 2 lines of code:
For the /edit/ route, I simply added this check.
if form.delete.data:
return redirect(url_for('servers.delete', id=id))
Which makes the entire edit route look like this:
def edit(id):
server = UcxServer.query.filter_by(id=int(id)).first_or_404()
form = EditForm(obj=server)
if form.delete.data:
return redirect(url_for('servers.delete', id=id))
if form.validate_on_submit():
form.to_model(server)
db.session.commit()
flash('Your changes have been saved.')
return render_template('addserver2.html', form=form)
Maybe you can use customized validators. Like this:
delete = SubmitField('Delete', validators=delete())
About how to make a function a customized validator, check this link. The custom validators section.
Related
I am very new to Python flask and webserver concept in general but have managed to create a simple webapp.
It basically consists of a home page with a form to fill in and a submit button which returns a flashed messages when : 1) all fields are filled correctly and 2) not all fields are filled.
My code looks like this:
#app.route('/', methods = ['GET', 'POST'])
def home():
form = preference_form(request.form)
print(form.errors)
if request.method == 'POST':
name = request.form['name']
age = request.form['age']
address = request.form['distance']
date = request.form['date']
if form.validate():
flash('All good!')
else:
flash('Oops! All details are required to provide accurate results!')
return render_template('home.html', form = form)
#app.route('/results', methods = ['POST'])
def return_results():
name = request.form.get('name')
age = request.form.get('age')
address = request.form.get('address')
result = function_a(name=name,
age=age,
address=address)
return result
The flash messages worked as desired but after I added the return_results() route, after the form is filled (whether complete or incomplete) it brings me straight to /results.
Could you please tell me what am I missing here?
Thank you!
You should render your flash messages in your template file. Add following code snippet in your template which you want to show the flash messages or your layout template file:
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
UPDATE: One view function with three execute path will meet your needs.
1)if the request method is get, just render the home.html without flash message;
2)if the request method is post and the form data pass the validation, render the
result.html with success flash message;
3)if the request method is post but the form data doesn't pass the validation, render the home.html again with the failed flash message.
#app.route('/', methods=["GET", "POST"]
def index():
form = PreferenceForm()
if request.method == "POST":
if form.validate_on_submit():
flash("success.")
result = func(age=form.age.data,
date=form.date.data,
name=form.name.data,
address=form.address.data)
return render_template("result.html", result=result)
else:
flash("failed!")
return render_template('home.html', form=form)
I want to set a default value for my queryselectfield. My code looks like this:
Template:
{% import "bootstrap/utils.html" as utils %}
{% import "bootstrap/wtf.html" as wtf %}
{% extends "base.html" %}
{% block title %}Request{% endblock %}
{% block body %}
<div class="content-section">
...
{{ form.country(class_="selectformfield") }
...
Route:
#requests.route('/request/add', methods=['GET', 'POST'])
#login_required
def add_request():
check_admin()
add_request = True
form = RequestForm()
if form.validate_on_submit():
...
Country = form.hostname.data
...
request = Request(...country=country, ...)
try:
# add request to the database
db.session.add(request)
db.session.commit()
flash('You have successfully added a new request.')
except:
# in case request name already exists
flash('Error: request already exists.')
# redirect to the request page
return redirect(url_for('requests.show_request', id=request.id))
# load request template
return render_template('requests/add_request.html', add_request=add_request,
form=form, title='Add new Request')
Form:
class RequestForm(FlaskForm):
...
country = QuerySelectField(query_factory=lambda: Country.query.all(), get_label="name")
...
I already tried it like this, but it didn't work.
default_country = query_factory=lambda: Country.query.filter(Country.id == '1')
country = QuerySelectField(query_factory=lambda: Country.query.all(), get_label="name", default=default_country)
SQLAlchemy/WTForms: set default selected value for QuerySelectField
I also already read this post here with a simmilar problem, but the solution doesn't work for me.
Can annyone help me?
Try this:
default=lambda: Country.query.filter(Country.id == '1').one_or_none())
here the complete code of your field definition:
country = QuerySelectField(query_factory=lambda: Country.query.all(), get_label="name", default=lambda: Country.query.filter(Country.id == '1').one_or_none())
I'm trying to use Flask-Security to login and register users. However, I'm trying to do two things. The first being change the default /registration to /signup which I believe I've done correctly.
The second is I want to customize the registration form. I can get the page loaded but whenever I submit the form nothing happens. No data is sent to the backend or inserted into the sqlite database.
I'm also not sure if I need to write my own app.route function to handle creating a new user and/or checking if they already exist. I'd like to be able to use flask-security's register but just tweak it. If that's even possible.
Here's my main python file:
from flask import Flask, redirect, flash, session, request, render_template
from flask_sqlalchemy import SQLAlchemy
import os, time
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
app.config['DATABASE'] = 'data.db'
app.config['SECURITY_TRACKABLE'] = True
app.config['SECURITY_REGISTERABLE'] = True
app.config['SECURITY_REGISTER_URL'] = '/signup'
app.config['SECURITY_REGISTER_USER_TEMPLATE'] = 'security/register.html'
# enable this if you want to send email and confirm
# app.config['SECURITY_CONFIRMABLE'] = True
db = SQLAlchemy(app)
from user import Security, User, user_datastore
from forms import logform, signupform, RegisterForm
security = Security(app, user_datastore, register_form=signupform, login_form=logform,
confirm_register_form=signupform)
db.create_all()
db.session.commit()
#app.route('/')
def hello_world():
log = logform(csrf_enabled=False)
flash("HELLO.")
return render_template("index.html", form=log)
#app.route('/login')
def login():
print "/LOGIN REQUESTED"
form = logform(csrf_enabled=False)
return render_template("security/login_user.html", login_user_form=form, security=security)
#not sure if I need this function at all
#app.route('/signup', methods=['GET', 'POST'])
def signup():
print "/SIGNUP REQUESTED"
form = signupform(csrf_enabled=False)
# form = RegisterForm()
if request.method == 'GET':
return render_template("security/register.html", register_user_form=form, security=security)
else:
#log = logform(csrf_enabled=False)
if form.validate_on_submit() or form.validate():
print "HERE NOW SOMEONE SUBMITTED SOMETHING"
print form.email.data
print form.username.data
print form.password.data
user_datastore.create_user(form)
db.session.commit()
return redirect('/')
I'm not sure if I need the /signup function or if flask-security will handle it on default.
Next here's my logform and signupform classes:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField
from wtforms.validators import DataRequired, Length, Email, EqualTo
from flask_security.forms import LoginForm, RegisterForm, Form
class logform(LoginForm):
login = StringField('login', validators=[DataRequired()])
# password = PasswordField('password', validators=[DataRequired()])
class signupform(RegisterForm):
# email = StringField('email', validators=[Email(), DataRequired()])
username = StringField('username', [DataRequired()])
# password = PasswordField('password', validators=[DataRequired()])
Here's the current registration form I'm trying to use. I'm not sure if I should use url_for('signup') as flask-security's default registration form uses url_for_security('register').
<!DOCTYPE html>
{% extends "base.html" %}
{% block content %}
<div id="signup">
<h1>Create Account.</h1>
<h3>TESTING</h3>
{# not sure what to put as my action. default flask-security uses url_for_security('register') #}
<form id="logfrm" name='register_form' method="POST" action="{{ url_for('signup') }}">
{# figure out how to make input required #}
{{ register_user_form.email(placeholder="email", type="email") }}<br>
{{ register_user_form.username(placeholder="username") }}<br>
{{ register_user_form.password(placeholder="password", type="password") }}<br>
{# register_user_form.confirm(placeholder="confirm password") #}<br>
{{ register_user_form.submit }}
<input type="submit" value="SIGNUP" >
</form>
</div>
{% endblock %}
Any help would be great, thanks!
Thanks for the help. That really cleared up most of the trouble I was having.
The only other thing wrong was in my form. I was forgetting that RegisterForm requires a password confirmation so I also added:
{{ register_user_form.password_confirm(...) }}
and to also include a app.config['SECRET_KEY'] = 'blah' in my main file so that the registration doesn't run into an error.
You don't need to define a new route for the registration.
In your signupform class that is inherited from RegisterForm you only need to override the validate method with your custom logic and return True or False as appropriate.
In your html template for registration the action url is {{ url_for_security('register') }}
The same applies for a custom login form - the url action though is {{ url_for_security('login') }}
I have been going through the Django forms 'tutorial'. Once I had read through the tutorial, I tried modifying it to suit my needs and customize it to learn it Django forms well. I discovered whenever I modified the form, the website would not update. I assume its an error with my code, but I have not been able to find it.
# views.py
def contact(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = ContactForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/message_recived/')
# forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(label='Name', max_length=100)
email = forms.EmailField(label='Email', max_length=100)
message = forms.CharField(label='Message', max_length=500)
# models.py
from django.db import models
class Contact(models.Model):
name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
message = models.CharField(max_length=500)
and here is the contact.html template:
#contact.html
{% extends "BlogHome/headerAndFooter.html" %}
{% block content %}
<script>
document.title = "Pike Dzurny - Contact"
</script>
<form action="/message_recived/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
Did I do something wrong? I have tried clearing my browsers cache, using a new browser, and obviously refreshing it.
Looks like your forget to render response inside your view.
Also you need to include form into context to render template right.
Try to change view as follow:
def contact(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = ContactForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/message_recived/')
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
I am new to Flask and I am trying to save form data from a Flask form to database using SQLAlchemy and I am not having any luck. I have tried several methods from research I found both here and outside of this forum.
When I take the simplistic route, the web form works and I can enter data but it will not populate the DB.
----Models----
class QIDMapping(db.Model):
id = db.Column(db.Integer, primary_key=True)
qid_number = db.Column(db.Integer)
br_field_name = db.Column(db.String(75))
vendor_field = db.Column(db.String(75))
----Forms----
class QIDForm(Form):
qidnumber = IntegerField('qidnumber', validators=[DataRequired()])
brfieldname = StringField('brfieldname', validators=[DataRequired()])
vendorfieldname = StringField('vendorfieldname')
----Views----
from flask import render_template, flash, redirect, session, url_for,
request, g
from flask_wtf import form
from app import app, db
from .forms import QIDForm
from .models import User, QIDMapping
from flask.ext.sqlalchemy import SQLAlchemy
#app.route('/qidmapping', methods=['GET', 'POST'])
def qid_map_update():
form = QIDForm()
return render_template('qidmapping.html',
title='QID Mapping',
form=form)
----qidmapping.html----
{% block content %}
<h1>Map QIDs to Vendor File</h1>
<form action="" method="POST">
{{form.hidden_tag()}}
<p>
Please enter the QID, BrassRing Field Name and Vendor Tag
<br>
<h2>QID Number {{ form.qidnumber(size=25) }}<br></h2>
<h2>BR Field {{ form.brfieldname(size=25) }}<br></h2>
<h2>Vendor Field {{ form.vendorfieldname(size=25) }}<br></h2>
</p>
<p><br>
</p>
<p><input type="submit" value="Save Fields">
</p>
</form>
{% endblock %}
I have also tried the method in this post Flask - WTForm - save form to db
and when I do, I get a Method Not Allowed error and I'm not sure why.
----view for question 20837209 format----
#app.route('/qidmapping', methods=['GET', 'POST'])
def qid_map_update():
form = QIDForm()
if form.validate_on_submit():
newform = (
form.qidnumber.data,
form.brfieldname.data,
form.vendorfieldname.data
)
db.session.add(newform)
db.session.commit()
return redirect('/qidmapping')
return render_template('qidmapping.html',
title='QID Mapping',
form=form)
Any help would be greatly appreciated!
Try replacing
newform = (
form.qidnumber.data,
form.brfieldname.data,
form.vendorfieldname.data
)
db.session.add(newform)
with
m = QIDMapping()
m.qid_number = form.qidnumber.data
m.br_field_name = form.brfieldname.data
m.vendor_field = form.vendorfieldname.data
db.session.add(m)
... and if that doesn't work. Do your standard POST troubleshooting:
1) Verify POST request
2) Ensure CSRF is working correctly.
3) Log validation errors / success
4) Check for DB exceptions