WTForms/flaskforms not retrieving data properly via submit button - python

So I'm just trying to get the submit button to work properly.
Work properly meaning to get the user input for email and password to be directed to my login.
Currently, it only redirects to the index.html, but I want it to go result with a redirect to either profile or error.
Here's the python part:
#app.route("/login", methods=["GET", "POST"])
def login():
"""Log user in if credentials provided are correct."""
form = LoginForm(request.post)
# this is if its POST
if form.validate and request.method == 'POST':
email = request.form['email']
password = request.form['password']
if email == admin#gmail.com" and password == "admin":
return redirect(url_for('/home'))
else:
return redirect(url_for('/error'))
# this is if its GET
#return render_template("index.html", form=form)
This is the login form
class LoginForm(FlaskForm):
email = StringField('email', validators=[InputRequired()])
password = PasswordField('password', validators=[InputRequired()])
remember = BooleanField('remember me')
Here's the html part:
<div class="modal-body">
<form role="form">
<div class="form-group">
<div class="input-group">
<form method="POST" action="{{ url_for('login')}}">
{{ form.csrf }}
<dl style="width: 100%;">
<div class="form-group">
<form role="form">
<div class="form-group">
<div class="input-group">
{{ wtf.form_field(form.email) }}
{{ wtf.form_field(form.password) }}
</div>
</div> <!-- /.form-group -->
</form>
</div> <!-- /.form-group -->
<div style="margin-left: 70%;" class="checkbox">
{{ wtf.form_field(form.remember) }}
</div>
<div class="modal-footer">
<input class="btn btn-lg btn-primary btn-block" style="background-color: #3eb2a0;border-color: #3eb2a0;" type="submit" value="Sign In">
</div>
</dl>
</form>
</div>
</div>
</form>
</div>

Only problems i see with your code is one:
if email == admin#gmail.com" and password == "admin":
return redirect(url_for('/home'))
You do not have a quotation mark before admin#gmail.com
two:
return redirect(url_for('/home'))
is there a reason for the forward slash? have you tried 'home'
edit:
Here is an example of how i set up views that are similar to yours
#bp.route('/upvote', methods=['GET', 'POST'])
def view():
form = key()
if form.validate_on_submit():
received_key = form.key_code.data
url = form.url.data
username = form.username.data
return redirect(url_for('views.success')) #views is the name of the blueprint the success route is in
return render_template('upvote.html', title='title here', form=form)
form.validate_on_submit():
Takes the place of form.validate and form.submit.data/if response.method ='POST'
and you can then retrieve the data stored in the forms by form.variable.data.
Check to see if you are even receiving data back from the forms at all. It seems like it might not be recieving the post request and skipping everything under your "if request.method = 'POST'" statement.
Your view would look like:
#app.route("/login", methods=["GET", "POST"])
def login()
form = LoginForm()
# this is if its POST
if form.validate_on_submit():
email = form.email.data
password = form.password.data
if email == "admin#gmail.com" and password == "admin":
return redirect(url_for('home'))
else:
return redirect(url_for('error'))
#return render_template("index.html", form=form)

Related

How to properly render form fields with django?

I am currently working on a login page for a django webapp. I am trying to include the login form within the index.html file. However, the form fields are not being rendered. My urls are correct I believe but I'm not sure where I am going wrong. Here is my views.py, forms.py and a snippet of the index.html. (I do not want to create a new page for the login I'd like to keep it on the index page)
# Home view
def index(request):
form = LoginForm()
if form.is_valid():
user = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password'],
)
if user is not None:
login(request, user)
messages.success(request, f' welcome {user} !!')
return redirect('loggedIn')
else:
messages.info(request, f'Password or Username is wrong. Please try again.')
return render(request, "index_logged_out.html")
class LoginForm(forms.Form):
username = forms.CharField(max_length=63)
password = forms.CharField(max_length=63, widget=forms.PasswordInput)
<!-- Login -->
<section class="page-section" id="login">
<div class="container">
<div class="text-center">
<h2 class="section-heading text-uppercase">Login</h2>
</div>
<form>
{% csrf_token %}
{{form}}
<center><button class="btn btn-primary btn-block fa-lg gradient-custom-2 mb-3" type="submit" style="width: 300px;">Login</button></center>
</form>
<div class="text-center pt-1 mb-5 pb-1">
<center><a class="text-muted" href="#!">Forgot password?</a></center>
</div>
<div class="d-flex align-items-center justify-content-center pb-4">
<p class="mb-0 me-2">Don't have an account?</p>
<button type="button" class="btn btn-outline-primary">Create New</button>
</div>
</form>
</div>
</section>
To add to A.S's answer, you should initialize a context variable at the start of the view.
def index(request):
context = {}
form = LoginForm()
context['form'] = form
if form.is_valid():
# ...
return render(request, "index_logged_out.html", context)
It makes it easier to work with when you start to pass in more variables to the context later on, otherwise it'll complicate your view.

error messages not displaying in login form

On my login page, when a user types an email address that is not registered yet or is in invalid email format it should give him an error message. But when I submit the form I do not get any errors. I tried to print form.errors and I get an empty dictionary. I used the same logic on registration and it is working there.
forms.py
class LoginForm(FlaskForm):
email = StringField("", validators=[DataRequired(), Email()])
password = PasswordField("", validators=[DataRequired()])
submit = SubmitField("LOG IN")
views.py
#users.route("/login", methods=["GET", "POST"])
def login():
form = LoginForm()
if form.validate_on_submit:
user = User.query.filter_by(email=form.email.data).first()
if user is not None and user.check_password(form.password.data):
login_user(user)
return redirect(url_for("core.home", user=user))
return render_template("login.html", form=form, total_quantity=session["total_quantity"])
login.html
<div id="login-container">
<h5>LOG IN</h5>
<p>Please enter your e-mail and password:</p>
<form method="POST">
{{form.hidden_tag()}}
{{form.email.label()}} {{form.email(placeholder=" Email", id="email")}}<br>
{% for error in form.email.errors %}
<span style="color: #e50000;">{{ error }}</span><br>
{% endfor %}
{{form.password.label()}} {{form.password(placeholder=" Password", id="password")}}<br>
{% for error in form.password.errors %}
<span style="color: #e50000;">{{ error }}</span><br>
{% endfor %}
{{form.submit(id="login")}}
<p>Not a member!
<a class="nav-link d-md-inline" href="{{ url_for('users.registration') }}" id="logreg-link"> REGISTER</a>
</p>
</form>
</div>
form.validate_on_submit() should be a function call. You forgot the parenthesis.

why the sentence if form.is_valid(): never pass. i have tried many thing, changing the python version for example and always is the same

When I run the code, it never pass the sentence if form.is_valid():
I have changed the version of python, but it is still the same
views.py
def login_page(request):
form = Loginform(request.POST or None)
context = {
"form": form
}
print("User logged in")
if form.is_valid():
# print("form is validated")
print(form.cleaned_data)
# print("form cleaned data")
username = form.cleaned_data.get("username")
password = form.cleaned_data.get("password")
forms.py
from django import forms
class Loginform(forms.Form):
username = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput)
view.html
<div class='container'>
<div class='row'>
<div class='col'>
<p>{{ content }}</p>
<div class='col-sm-6 col-12'>
<form method='POST'> {% csrf_token %}
{{ form }}
<buttom type='submit' class='btn btn-default'>Submit</buttom>
</form>
</div>
</div>
</div>
</div>
# The form looks well, same the submit. I do not see the error
please help me to undertand what happens with this sentence of form_is_valid

how to get username from login form, when reset password link is clicked django

I am trying to get the username from my login form when the reset password link has been pressed.
view.py
def ResetPassword(request):
if request.method == 'POST':
username = request.Post.get['login_username']
if username:
#send password reset link via email
else:
#if username is empty search for your account
return render(request, 'accounts/forms/email_search.html',{})
forms.html
<form class="navbar-form navbar" method="POST"action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
{{ form.login_username }}
</div>
<div class="form-group">
{{ form.login_password }}
</div>
<button type="submit" id="loginBtn" class="btn btn-default">Submit</button>
<br>
Reset Password
</form>
First of all, the request object has not attribute Post, but POST.
So, it should be either
# use this if you're sure that login_username will always be passed
`username = request.POST['login_username']`
or
# use this and in case login_username fails, then an empty string is returned
`username = request.POST.get('login_username', '')`.
Now, to your problem. The form has a submit input only for the login view. The change password button is just a plain link. Thus, when you click on it you make a GET request to the ResetPassword view (by the way, you should rename it to reset_password, it's the Python way), without any arguments passed.
To fix this, you must remove this link from inside the form.
Then you have to create the template for the ResetPassword view, say reset_password.html and inside there create another form (with only the username field required) that will POST to ResetPassword view.
For example:
<!-- reset_password.html -->
<form class="navbar-form navbar" method="POST" action="{% url 'ResetPassword' %}">{% csrf_token %}
<div class="form-group">
<input type="text" name="login_username" required />
</div>
<button type="submit" id="reset-pwd-btn" class="btn btn-default">Reset Password</button>
</form>
And last:
# ResetPassword.py
def ResetPassword(request):
if request.method == 'POST':
# login_username is the same as the input's name
username = request.POST.get('login_username')
if username:
# send password reset link via email
else:
# if username is empty search for your account
return render(request, 'accounts/forms/email_search.html', {})
return render(request, 'accounts/forms/reset_password.html', {})

BadHeaderError using Flask with FlaskMail and Postfix on Ubuntu server

I'm running a fullstack website with Flask and SQLite. On the page I have a contact-section to let visitors send me an email. The contact-section consists of an HTML form which sends the information to the webserver via HTTP POST. The server itself uses the FlaskMail plugin to create the message and send it to the mail-server (in this case a postfix server I set up on the same server).
However, I'm getting a BadHeaderError every time I click submit.
I already looked for existing fixes and found an existing Stackoverflow question here. However, the solution there seems to be unrelated to my issue.
Relevant code from webserver.py (Flask python file):
app = Flask(__name__)
app.debug = True
app.config['MAIL_USERNAME'] = 'admin'
app.config['MAIL_PASSWORD'] = 'password'
app.config['MAIL_USE_TLS'] = True
mail = Mail(app)
#app.route('/contact', methods=['GET', 'POST'])
def contact():
lang = get_lang(request.headers)
if request.method == 'GET':
if lang == 'de':
return render_template('contact.html', lang=lang, title=title_de, descriptio$
else:
return render_template('contact.html', lang=lang, title=title_en, descriptio$
elif request.method == 'POST':
name = request.form['name']
email = request.form['email']
company = request.form['company']
message = request.form['message']
if not name:
flash('Please enter your name')
return redirect(url_for('contact'))
if not email:
flash('Please enter your e-mail address')
return redirect(url_for('contact'))
if not message:
flash('Please enter a message')
return redirect(url_for('contact'))
message += '\n\n'
message += ('Name: ' + name)
message += '\n\n'
message += ('Company: ' + company)
msg = Message(message, sender=email, recipients=['pawelczyk.johannes#gmail.com'])
mail.send(msg)
flash('You will receive an automatic confirmation mail')
return redirect(url_for('index'))
else:
flash('Bad request')
return redirect(url_for('index'))
Apache error log: pastebin
HTML:
<div id="contact-form-container">
<form id="contact-form" action="{{ url_for('contact') }}" method="post">
<div>
<div class="contact-form-row">
<h3 class="to-left">Name:</h3>
<input class="to-right" type="text" name="name" placeholder="Name">
</div>
<div class="contact-form-row">
<h3 class="to-left">E-Mail:</h3>
<input class="to-right" type="text" name="email" placeholder="E-Mail">
</div>
<div class="contact-form-row">
<h3 class="to-left">Firma (optional):</h3>
<input class="to-right" type="text" name="company" placeholder="Firma">
</div>
<h3 class="gap-over">Ihre Nachricht:</h3>
<textarea cols="40" rows="10" name="message"></textarea></br>
</div>
<div class="middle">
<input class="button" type="submit" value="Senden">
</div>
</form>
</div>

Categories