I've been searching a long time for examples on how to use checkboxes with Flask WTF, but it seems like either there are no example or there are really complex ones that involve a list of checkboxes.
I did find one example in Miguel's blog here, but I'm not able to get the checkbox to render. Here's what I did:
First off, the form class:
class LoginForm(Form):
email = TextField("Email address", validators=[validators.required()])
password = PasswordField("Password", validators=[validators.required()])
remember_me = BooleanField("Remember me", default = False)
submit = SubmitField("Login")
And then in my template:
<form class="form-signin" role="form" action="{{ url_for('login') }}" method="post">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.email.label }}
{{ form.email ( ** {'class' : 'form-control'} ) }}
</div>
<div class="form-group">
{{ form.password.label }}
{{ form.password ( ** {'class' : 'form-control'} ) }}
</div>
<div class="form-group">
{{ form.remember_me }} Remember me
</div>
</form>
In the final output of the form, the checkbox is missing:
If I see the generated HTML, the field is just missing:
<form class="form-signin" role="form" action="/login" method="post">
<div style="display:none;"><input id="csrf_token" name="csrf_token" type="hidden" value="1457326344##3036eeab4ffa39494ee92247925a30a88a69432f"><input id="next" name="next" type="hidden" value=""></div>
<div class="form-group">
<label for="email">Email Address</label>
<input class="form-control" id="email" name="email" type="text" value="">
</div>
<div class="form-group">
<label for="password">Password</label>
<input class="form-control" id="password" name="password" type="password" value="">
</div>
<div class="form-group">
Remember me
</div>
<div class="form-group">
<input class="btn btn-primary btn-lg" id="submit" name="submit" type="submit" value="Login">
</div>
</form>
Curiously, if I try to add {{ form.remember_me.label }} to the template, I get an exception that jinja2.exceptions.UndefinedError: 'flask_security.forms.LoginForm object' has no attribute 'remember_me'.
I also came across some solutions that mention custom widgets, but I'm really hoping to hear I won't have to go that route for a simple, single checkbox.
What am I doing wrong? If nothing, what's the shortest, most painless way to accomplish this?
~~~~Update~~~~
It looks like there's some weird behavior at work here. The field form.remember seems to produce a checkbox, and form.remember.label produces a default "Remember Me" label. Using any other name causes the aforesaid Exception to occur.
I eventually found my mistake. The import from security import * caused a flask-security template LoginForm to creep into my namespace, causing the weird behavior. I also needed to make some changes to my forms, importing the Form from flask.ext.wtf but the rest of the fields from wtforms. Hope it helps somebody!
Related
{% csrf_token %}
User name
</div>
<div class="form-group">
<label class="form-label" for="form2Example2">Password</label>
<input type="password" id="form2Example2" class="form-control" name="password" required/>
</div>
<button type="button" class="btn btn-primary btn-block mb-4">Sign in</button>
i try to post data like email id and password in post method , but it sent through get method . I think there may be problem with bootstrap. can u tell me what are the modifications to be done in the bootstrap for post data method.
thanks
If you want to send it as post, then use button type: "submit". Also you might need form section, if you don't have it. Like this:
<form method="POST">
{% csrf_token %}
<div class="form-group">
(...)
</div>
<button type="submit" class="btn btn-primary btn-block mb-4">Sign in</button>
</form>
You need to add method = "POST" with {% csrf_token %} and submit button
<form method="POST">
{% csrf_token %}
<div class="form-group">
<label>Email address</label>
<input type="email" class="form-control">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Signin</button>
</form>
I am working on a job portal system. I provide users the chance to edit their profiles by adding and removing job experiences. The issue is I don't know how to send that data to the view so that it can retrieve all the fields and store them in the database accordingly. By retrieving, I mean for each job experience, retrieve their corresponding sub fields
Here is my template file:
<!--JOB EXPERIENCE-->
<div class="job_experience">
<h5>Experience</h5>
<hr>
<!--FORM-->
<form action="#" id="save_job_experience_form" method="POST">
{% csrf_token %}
<div class="job_container">
{% for job in job_experience %}
<div class="exp">
<label>Organisation</label>
<input type="text" class="form-control" name="organisation
placeholder="Organisation" value="{% if job.organisation %}
{{job.organisation}}{% endif %}" required>
<label>Job Title</label>
<input type="text" name="job_title" class="form-control" value="{% if job.job_title
%}{{ job.job_title }}{% endif %}" placeholder="Job Title e.g Backend Developer"
required>
<button style="margin-left:15px;" type="button" class="btn btn-danger
remove_job_exp"><strong>Delete Job Experience</strong></button>
</div>
<hr>
{% endfor %}
</div>
<!--BUTTONS-->
<input type="submit"value="Save">
<input type="button" id="add_job_experience"value="Add one">
</form>
</div>
<script>
$(document).on('click', '#add_job_experience',function(e){
e.preventDefault();
$(".job_container").append(`<div class="exp">
<!--IT GOES ON AS ABOVE -->
$(document).on('click', 'button.remove_job_exp', function(e){
e.preventDefault();
$(this).closest('div.exp').remove();
});
You can post multiple inputs with the same name like so:
<input type="text" name="job[]" value="job1"/>
<input type="text" name="org[]" value="org1"/>
<input type="text" name="job[]" value="job2"/>
<input type="text" name="org[]" value="org2"/>
Then in django you can parse the POST data like so:
#require_POST #require POST method or check if request method is POST
def add_jobs(request):
jobs = request.POST.getlist('job[]')
orgs = request.POST.getlist('org[]')
...
Or use Django Formsets: https://docs.djangoproject.com/en/3.2/topics/forms/formsets/
I am working with Django templets and I am trying to create a beautiful login page.
I want to use this snippet to beautify my login page input fields.
<div class="form-label-group">
<input type="username" id="inputuser" class="form-control" placeholder="Email address" required autofocus>
<label for="inputuser">Username</label>
</div>
<div class="form-label-group">
<input type="password" id="inputPassword" class="form-control" placeholder="Password" required>
<label for="inputPassword">Password</label>
</div>
</div>
where should I keep my {{form.username}} and {{form.password}} in the above snippet
The input fields UI should look like :
But my UI looks like :
my urls.py has :
path('login/', auth_views.LoginView.as_view(template_name='post/login.html'), name='login'),
Where should i add the form fields so that i can get the desired UI for my input fields
The {{form.username}} will go inplace of input type="username" and {{form.password}} inplace of input type password this will create default email boxes.
If you want to use your own UI just make sure, the input html element has corresponding name="username" and name="password" as an attribute.
<div class="form-label-group">
<input type="username" id="inputuser" name="username" class="form-control" placeholder="Email address" required autofocus>
<label for="inputuser">Username</label>
</div>
<div class="form-label-group">
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
<label for="inputPassword">Password</label>
</div>
</div>
By using django-widget-tweaks I was able to create this beautiful login page.
We just need to add the class name to the render_field
Tweak the form field rendering in templates, not in python-level form definitions. Altering CSS classes and HTML attributes are supported.
That should be enough for designers to customize field presentation (using CSS and unobtrusive javascript) without touching the python code.
The changes which I made are:
{% load widget_tweaks %}
<div class="form-label-group">
{% render_field form.username placeholder=form.username.label class+="form-control" %}
<label for="id_username">User name</label>
</div>
<div class="form-label-group">
{% render_field form.password placeholder=form.password.label class+="form-control" %}
<label for="id_password">Password</label>
</div>
widget_tweak is an excellent solution. Here are the steps to install.
pip install django-widget-tweaks.
add 'widget_tweaks' to APPLICATION_INSTALLED in settings.py.
use in template.
{% load widget_tweaks %}
I'm currently trying to override a Django allauth template. So far, I followed all the recommendations on similar questions to mine:
overriding default templates of django-allauth
How to override template in django-allauth?
However, my goal is just change the default Django allauth without making new views or forms. (In previous projects I used to override the default forms constructor classes with the helper of Django Crispy Forms which is not possible in this particular case.)
I believe there is a way to ignore the {{form}} variable and just define a working form from scratch. Currently, I have my template being successfully being displayed when I navigate to 'account_login'. However, when I press Sign In nothing happens.
Here is my myapp/templates/account/login.html file:
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}
Sign In to {{ SITE_NAME }}
{% endblock %}
{% block body %}
<div class="centered">
<img class="logo" src={% static 'imgs/logo.png' %} alt="" width="100" height="100">
<form id="login_form" class="form-signin" method="post" action="{% url 'account_login'%}">
{% csrf_token %}
<label for="inputLogin" class="sr-only">Email address or Username</label>
<input type="text" id="login" class="form-control" placeholder="Email or Username" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="password" class="form-control" placeholder="Password" required>
<div class="note mb-3">
<label>
<input type="checkbox" value="remember" id="remember"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<div class="note mb-3 text-center">
<p>Forgot? Retrieve your login.</p>
<p>Not registered? <a href={% url 'account_signup'%}>Sign Up!</a></p>
</div>
</form>
</div>
{% endblock %}
Yes, you can customize it the way you want. It is rather simple.
When you use {{ form.as_p }} the page renders the form. And if you inspect the form you will notice that the page rendered the following form:
notice the id="" and the name="" you have to name it the exact same.
With that your code should look like this:
<form id="login_form" class="form-signin" method="post" action="{% url 'account_login'%}">
{% csrf_token %}
<label for="inputLogin" class="sr-only">Email address or Username</label>
<input type="text" name="login" id="id_login" class="form-control" placeholder="Email or Username" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" id="id_password" class="form-control" placeholder="Password" required>
<div class="note mb-3">
<label>
<input type="checkbox" name="remember" value="remember" id="id_remember"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<div class="note mb-3 text-center">
<p>Forgot? Retrieve your login.</p>
<p>Not registered? <a href={% url 'account_signup'%}>Sign Up!</a></p>
</div>
</form>
And you should be good to go.
So, I have this in my template:
<form action="./validate_code/" method="POST">
{% if error %}
<p>Sorry, that wasn't right.</p>
{% endif %}
<label for="class_code">Your class code: </label>
<input type='text' id='class_code'/>
<input type="color" id="color"/>
{% csrf_token %}
<input type="submit" value="submit">
</form>
Which compiles to:
<form action="./validate_code/" method="POST">
<label for="class_code">Your class code: </label>
<input type='text' id='class_code'/>
<input type="color" id="color"/>
<input type='hidden' name='csrfmiddlewaretoken' value='tGA4jKF1pd1QFC6NSAM9eNFvZqss0r4m' />
<input type="submit" value="submit">
</form>
And when I click submit, firefox sends this parameter:
csrfmiddlewaretoken:"tGA4jKF1pd1QFC6NSAM9eNFvZqs60r4m"
That's it. No text, no color. I have no idea what's going on.
None of your fields have a name attribute, so the browser sends no data.
You should really be using Django's forms framework for this, though.
As mentioned above, you need to specify a "name" attribute in your input fields. You don't need to use Django forms, but if you are submitting the form normally, any fields you are expecting to be sent need to have a name.
<form action="./validate_code/" method="POST">
{% if error %}
<p>Sorry, that wasn't right.</p>
{% endif %}
<label for="class_code">Your class code: </label>
<input type="text" name="class_code" id="class_code">
<input type="color" name="color">
{% csrf_token %}
<button type="submit">Submit</button>
</form>