I'm having trouble getting error messages in Flask to render.
I suspect this is related to the blueprints. Previously, the logic seen in views.py was in the users blueprint, but I've since ported it over to the main blueprint. Anyhow, since then, I am unable to get error messages to render.
The specific line I think I'm having trouble with is:
self.email.errors.append("This Email is already registered")
project/main/views.py
#main_blueprint.route('/', methods=['GET', 'POST'])
#main_blueprint.route('/<referrer>', methods=['GET', 'POST'])
def home(referrer=None):
form = RegisterForm(request.form)
# prepares response
resp = make_response(render_template('main/index.html', form=form))
if form.validate_on_submit():
do_stuff()
return resp
project/main/index.html
<h1>Please Register</h1>
<br>
<form class="" role="form" method="post" action="">
{{ form.csrf_token }}
{{ form.email(placeholder="email") }}
<span class="error">
{% if form.email.errors %}
{% for error in form.email.errors %}
{{ error }}
{% endfor %}
{% endif %}
</span>
</p>
<button class="btn btn-success" type="submit">Register!</button>
<br><br>
<p>Already have an account? Sign in.</p>
</form>
project/user/forms.py
class RegisterForm(Form):
email = TextField(
'email',
validators=[DataRequired(), Email(message=None), Length(min=6, max=40)])
def validate(self):
print "validating"
initial_validation = super(RegisterForm, self).validate()
if not initial_validation:
print "not initial validation"
return False
user = User.query.filter_by(email=self.email.data).first()
print user
if user:
print self
print "error, email already registered"
self.email.errors.append("This Email is already registered")
return False
return True
When attempting to debug, the value for 'print user' from this is:
project.user.forms.RegisterForm object at 0x7fa436807698
Got it to work, #glls, you were correct.Rewrote the code as:
#main_blueprint.route('/', methods=['GET', 'POST'])
#main_blueprint.route('/<referrer>', methods=['GET', 'POST'])
def home(referrer=None):
# prepares response
resp = make_response(render_template('main/index.html', form=form))
if form.validate_on_submit():
do_stuff()
form = RegisterForm(request.form)
return resp
Related
I have following scenario.
User fills out a form
If the user clicks the "continue" button and the form is valid the user will be redirected to a summary view
In the summary view the user checks the input again. He can either continue or go back.
If he continues the data will be saved in the database, if he goes back he can edit the form.
Since in step 4 the user is at the view summary I have to redirect him to the home view. I don´t want the user to fill out the entire form again, the previously entered data should be autofilled if he goes back.
Something special: I am using django-tagify2 for one input in the form to get tags rather then text. If the user goes back the tags should be rendered correctly in the tagify specific form.
So here are my files:
home.html
{% extends "messenger/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="message-container">
<form method="POST" autocomplete="off">
{% csrf_token %}
{{ form|crispy }}
<button name="sendmessage" class="btn btn-outline-info" type="submit">Continue</button>
</form>
</div>
{% endblock content %}
summary.html
{% extends "messenger/base.html" %}
{% block content %}
<h4>Zusammenfassung</h4>
<p><b>Empfänger: </b>{{ receiver }}</p>
<br>
<p><b>Betreff: </b>{{ subject }}</p>
<br>
<p><b>Nachricht: </b>{{ message }}</p>
<button>Edit</button>
<button>Continue</button>
{% endblock content %}
home view
#login_required(login_url='login')
def home(request):
if request.method == 'POST' and 'sendmessage' in request.POST:
message_form = MessageForm(request.POST)
if message_form.is_valid():
receiver_list = message_form['receiver'].value().split(';')
subject = message_form['subject'].value()
message = message_form['textmessage'].value()
#create sessions and send data to next view
session_receiver = receiver_list
request.session['session_receiver'] = session_receiver
session_subject = subject
request.session['session_subject'] = session_subject
session_message = message
request.session['session_message'] = session_message
return redirect('summary')
else:
message_form = MessageForm()
return render(request, 'messenger/home.html', {'form': message_form})
summary view
def summary(request):
receiver = request.session.get('session_receiver')
subject = request.session.get('session_subject')
message = request.session.get('session_message')
return render(request, 'messenger/summary.html', {'receiver':receiver,
'subject':subject,
'message':message})
So what is the best way to do this?
Can I use the session variables to set the fields in the form?
I don´t want to change the logic in the app. I want a home/summary/success view/template where I can loop as long is I want between home and summary until the user is happy with his entered form data
How about checking request.session when there is get request to home view? Then you can bind message_form = MessageForm() to session data.
You can check out htmx and django-htmx. You can do what you want easily without session by swapping HTML with context.
I played around with the session values and views and finally got a way to redirect to other views with prefilled form fields based on session values.
#login_required(login_url='login')
def home(request):
if request.method == 'POST' and 'sendmessage' in request.POST:
message_form = MessageForm(request.POST)
if message_form.is_valid():
ad_group = message_form['ad_group'].value().split(';')
ad_user = message_form['ad_user'].value().split(';')
subject = message_form['subject'].value()
message = message_form['textmessage'].value()
#create sessions and send data to next view
session_ad_group = ad_group
request.session['session_ad_group'] = session_ad_group
session_ad_user = ad_user
request.session['session_ad_user'] = session_ad_user
session_subject = subject
request.session['session_subject'] = session_subject
session_message = message
request.session['session_message'] = session_message
return redirect('summary')
else:
if request.session.get('session_subject'):
message_form = MessageForm(initial={'ad_group': request.session.get('session_ad_group'),
'ad_user': request.session.get('session_ad_user'),
'subject': request.session.get('session_subject'),
'textmessage': request.session.get('session_message')})
return render(request, 'messenger/home.html', {'form': message_form})
else:
message_form = MessageForm()
return render(request, 'messenger/home.html', {'form': message_form})
def summary(request):
ad_group = request.session.get('session_ad_group')
ad_user = request.session.get('session_ad_user')
subject = request.session.get('session_subject')
message = request.session.get('session_message')
if request.method == 'POST' and 'edit' in request.POST:
message_form = MessageForm(initial={'ad_group':ad_group, 'ad_user': ad_user,
'subject':subject, 'textmessage':message})
return render(request, 'messenger/home.html', {'form': message_form})
return render(request, 'messenger/summary.html', {'ad_group':ad_group,
'ad_user': ad_user,
'subject':subject,
'message':message})
Template
{% extends "messenger/base.html" %}
{% block content %}
<h2>Zusammenfassung</h2>
<div class="border-top pt-3">
<p><b>AD-Gruppe: </b>{{ ad_group }}</p>
<p><b>AD-User: </b>{{ ad_user }}</p>
<br>
<p><b>Betreff: </b>{{ subject }}</p>
<br>
<p><b>Nachricht: </b>{{ message }}</p>
<div class="buttoncontainer">
<form name="edit" action="" method="post">
{% csrf_token %}
<button class="btn edit_btn" formaction="{% url 'messenger-home' %}">Zurück</button>
</form>
<form name="senden" action="" method="post">
{% csrf_token %}
<button class="btn continue_btn" formaction="{% url 'send_messages' %}">Nachricht senden</button>
</form>
</div>
</div>
{% endblock content %}
I am learning Python, Flask and WTForm. What I aim for is that after I enter the email and password as required on the "/login" HTML page, and click the "Log In" button as defined in the CommentForm class, the page will be navigated to "success" or "denied" page. However, the code isn't working. After I click the button, the page stays still, instead of navigating to a different page. Does anything go awry regarding the code below? Thanks.
in main.py ⬇️
class CommentForm(FlaskForm):
email = StringField(label="Email", validators=[Email()])
password = PasswordField(label="Password", validators=[DataRequired(), Length(min=8)])
submit = SubmitField(label="Log In")
recaptcha = RecaptchaField()
#app.route("/login", methods=['GET', 'POST'])
def login():
form = CommentForm(request.form)
if request.method == 'POST' and form.validate():
if form.email.data == "admin#email.com" and form.password.data == "12345678":
return render_template("success.html")
else:
return render_template("denied.html")
return render_template("login.html", form=form)
in login.html ⬇️
<form method="post" action="{{ url_for('login') }}">
{{ form.csrf_token }}
{{ form.email.label }}<br>
{{ form.email(rows=1, cols=30) }}
{% for err in form.email.errors %}
<span style="color:red">{{err}}</span>
{% endfor %}<br>
{{ form.password.label }}<br>
{{ form.password(rows=1, cols=30) }}
{% for err in form.password.errors %}
<span style="color:red">{{err}}</span>
{% endfor %}<br>
{{form.submit}}
</form>
I tried to run your code (and as well tried some changes)
Python
#app.route("/login", methods=['GET', 'POST'])
def login():
if request.method == "GET":
form = CommentForm(request.form)
return render_template("login.html", form = form)
elif request.method == 'POST':
form = CommentForm(request.form)
if form.validate_on_submit():
if form.email.data == "admin#email.com" and form.password.data == "12345678":
return "Welcome User"
elif not form.validate_on_submit():
print(form.errors)
return "Hey it is invalid"
return "??"
This results to the elif being called with an error of
{'recaptcha': ['The response parameter is missing.']}
To solve this
Add {{form.recaptcha}} on your login.html
Go to https://www.google.com/recaptcha/admin/create
Fill up the form and get a public and private key
On your flask application set
app.config["RECAPTCHA_PUBLIC_KEY"] = "yourkey"
app.config["RECAPTCHA_PRIVATE_KEY"] = "yourkey"
I'm trying to set up a basic "Contact" form for my website, which will basically take in values and then put them into a CSV file. The issue I'm having is that the entries cannot be validated cause they're missing a csrf_token?
Here's the relevant code from my app.py:
#app.route('/contact_end', methods=['POST'])
def handle_contact():
form = ContactForm()
print(form.name.data)
if form.validate_on_submit():
print("yup")
with open('data/messages.csv', 'a') as f:
print("oh shit")
writer = csv.writer(f)
writer.writerow([form.name.data, form.email.data, form.message.data])
print("waddup")
return redirect(url_for('contact_handler.html'), name=form.name.data)
print(form.errors)
return render_template('contact.html', form=form)
It skips over the if statement as it never ends out printing the "yup", and instead it prints out the error:
{'csrf_token': ['The CSRF token is missing.']}
The template that this connects to is:
{% extends "base_template.html" %}
{% block title %}Contact us {% endblock %}
{% block content %}
<p>Feel free to use the contact form below to send us any questions you might have.</p></br>
<form action="/contact_end" method="post">
{{ form.csrf_token }}
<label>Your Name <input type="text" name="name"/></label></br>
<label>Your Email <input type="text" name="email"/></label></br>
<label>Your Name <textarea name="message"></textarea></label></br>
<button type="submit">Send</button>
<button type="reset">Clear</button>
</form>
{% endblock %}
I've tried messing with form.csrf_token and .hidden_tags(), but with no success.
As well, this is the initial part of app.py that brings you to the page in the first place, the one above is the endpoint for the form:
#app.route('/contact')
def contact():
return render_template('contact.html', form=form)
Finally, here's my ContactForm class:
class ContactForm(FlaskForm):
print("yep")
name = StringField('Name', validators=[InputRequired()])
email = EmailField('Email', validators=[InputRequired(), Email()])
message = TextAreaField('Message', validators=[InputRequired()])
I've made sure to set my secret key, as well. Anyone have any idea why this isn't working? Many thanks.
You still need to create the form instance in your contact() function:
#app.route('/contact')
def contact():
form = ContactForm()
return render_template('contact.html', form=form)
I am trying to show an error when the user enters wrong login credentials using form_template. So far I tried the below approach but it is not working.
Forms.py:
class UserForm(forms.Form):
username=forms.CharField(max_length=50)
password=forms.CharField(widget=forms.PasswordInput)
model=User
fields=['username', 'password']
Views.py:
class loginform(View):
template_name='essay/Login.html'
form_class=UserForm
def get(self,request): # if the request is get then only view the function
form=self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self,request):
form=self.form_class(request.POST)
if form.is_valid():
#user = form.save(commit=False) # it doesnot save in database, it is used to et clean the values
# clean data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
# authenticate user:
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
if(request.user.is_prof==True):
return redirect('essay:file', )
else:
return redirect('essay:stdprofile')
else:
return render(request,self.template_name, {
'error_message': ' Login Failed! Enter the username and password correctly', })
else:
msg = 'Errors: %s' % form.errors.as_text()
return HttpResponse(msg, status=400)
return render(request, self.template_name, {'form': form})
Form_template:
{% for field in form %}
<div class="form-group">
<label class="control-label col-sm-2">{{ field.label_tag }}</label>
<div class="col-sm-10">{{ field }}</div> <!-- inputs on the rigth -->
</div>
{% endfor %}
Login.html:
<body>
<div class="login-card">
<h1>Log-in</h1><br>
<form class="form-horizontal" action="" method="POST" enctype="multiport/form-data">
{% csrf_token %}
{% include 'essay/form_template.html' %}
<input type="submit" name="login" class="login login-submit" value="login">
</form>
{% error_message %}
</div>
</body>
The problem I got when I enter invalid credentials, username and password fields vanish and it also does not display the error message.
In your field in form page add,
{{field.errors}}
or under csrf tag add,
{{form.errors}}
This will show all your field errors, for non field errors add,
{{form.non_field_errors}}
Also, you can also use Django builtin messages to display your custom message.
The error is because you are using {% error_message %}in your template, when the correct is {{ error_message }}.
Plus,
why not use Django messages?
You also can easily include message on Class Based Views - see here
I was asked to Create a simple Flask app which stores just a single text
field, On a single web page, and on which the user should see a form with the "message"
field. Below the form should be a list of existing messages in the
database. When user types something in the "message" field and submits the
form, the "message" should be saved to a table in SQLite. AND After the message is saved, user should come back to the page with the form and message list.
I am stuck at a POINT
I am not being able to SUBMIT the message
My page do retrieve messages from the database which is already stored in the database while I created it.
But Can SOMEONE please guide for the codes to SUBMIT the message filled in the form.
My message.html code is:
{% extends "template.html "%}
{% block content %}
<h2>You are in the Message Page</h2>
<br/>
<p><h4>In this page, You can view the Existing Messages and can also Submit your own message.</h4></p>
<br/><br/>
<h3>Enter Your Message:</h3><br/>
<form action="" method='POST'>
<dl>
<dt>Message:
<dd><input type="text" name=msg_msg maxlength=80 style="width:300px">*Maximum Length = 80
</dl>
<input type=submit value="Submit Message">
</form>
<h3>The Existing Messages:</h3>
{% for item in message %}
Msg_ID: <B>"{{ item.msg_id }}"</B><br/>Message: {{ item.msg_msg }} <br/><br/>
{% endfor %}
{% endblock %}
and my routes.py code for this is:
#app.route('/message')
def message():
g.db = connect_db()
cur = g.db.execute('select msg_id, msg_msg from msg')
message = [dict(msg_id=row[0], msg_msg=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template('message.html', message=message)
#app.route('/message', methods=['GET', 'POST'])
def message_1():
error = None
if request.method == 'POST':
for request.form['input_msg'] = text:
g.db = connect_db()
cur = g.db.execute('insert into msg_msg from msg')
message = [dict(msg_id=row[0], msg_msg=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template('message.html', message=message)
#error = 'Invalid Entry, Please Try Again.'
else:
# session['logged_in'] = True
return redirect(url_for('message'))
return render_template('message.html' , error=error)
Use 1 message view
#app.route('/message', methods=['GET', 'POST'])
def message():
cur = db.execute('select id,msg from msg_msg')
message = [dict(msg_id=row[0], msg_msg=row[1]) for row in cur.fetchall()]
if request.method == 'POST':
g.db = connect_db()
cur = g.db.execute('insert into msg_msg (msg) values (?)',request.form['input_msg'])
message = [dict(msg_id=row[0], msg_msg=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template('message.html' , message = message)
message.html
{% extends "template.html "%}
{% block content %}
<h2>You are in the Message Page</h2>
<br/>
<p><h4>In this page, You can view the Existing Messages and can also Submit your own message.</h4></p>
<br/><br/>
<h3>Enter Your Message:</h3><br/>
<form action={{ url_for('message') }} method='POST'>
<dl>
<dt>Message:
<dd><input type="text" name=msg_msg maxlength=80 style="width:300px">
</dl>
<input type=submit value="Submit Message">
</form>
<h3>The Existing Messages:</h3>
{% for item in message %}
Msg_ID: <B>"{{ item.msg_id }}"</B><br/>Message: {{ item.msg_msg }} <br/><br/>
{% endfor %}
{% endblock %}