Django crispy forms shows password as clear text - python

Crispy forms currently shows my password field as clear text. I have tried the following but I still cannot get it to use type=password.
Fieldset(
'Enter a password.',
PrependedText('password', '<i class="fa fa-key"></i>',
placeholder='Password',
autocomplete='off',
widget=forms.PasswordInput,
),
),
I have also tired type="password" with no effect.
I get no error.

I'm 99.9% positive that you missed adding the widget to the form field declaration. You should have something like this in order to display a password field:
class MyForm(forms.Form):
...
password = forms.CharField(widget=forms.PasswordInput)
...
And the layout should be as simple as:
Layout(
PrependedText('password', '#', placeholder="password", autocomplete='off')
)
The widget= keyword argument is defined on the Django's forms.CharField constructor and not on the django-cryspy-forms' bootstrap.PrependedText constructor.
You can find more information on Django forms fields here.
UPDATE
If you have a model form, it's being constructed from your model, either automatically (eg using the admin views), by using modelform_factory or by defining the ModelForm yourself. Here is an example of the 3rd approach.
class MyModelForm(forms.ModelForm):
class Meta:
fields = (... fields you want to include in the form ...)
password = forms.CharField(widget=forms.PasswordInput, ...)
Please note that by providing your model form field override, you'll have to also provide attributes like label, help_text (and such) because they will not be automatically copied from the model field.

I never had good luck with crispy-forms and formsets, so I just use forms directly in templates. See if that works:
<form method="post">{% csrf_token %}
{{ formset.management_form|crispy }}
{% for form in formset %}
<input id="id_form-{{ forloop.counter0 }}-id" name="form-{{ forloop.counter0 }}-id" type="hidden" value="{{ form.instance.pk }}"/>
{{ form|crispy }}
{% endfor %}
</form>

You need to define PasswordInput.
class YourForm(forms.ModelForm):
password = forms.CharField(label='Enter Password',widget=forms.PasswordInput(attrs={'placeholder': 'alphanumeric password'}))

Related

MultipleChoiceField django python, impossible display datas in the template

I have big problem, I use MultipleChoic Field into django for "input multiselect",
a user at the possibility of make many choices via the "input select multiple"
I explain to you :
I use this Package : https://pypi.org/project/django-multiselectfield/
this is my model :
class Profil(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,)
skill = MultiSelectField(max_length=500, null=True, blank=True, choices=Skillz)
board = MultiSelectField(max_length=500, null=True, blank=True, choices=Boardz)
this is my form :
class ProfilForm(forms.ModelForm):
skill = forms.MultipleChoiceField(required=False, widget=forms.SelectMultiple, choices=Skillz)
board = forms.MultipleChoiceField(required=False, widget=forms.SelectMultiple, choices=Boardz)
this is my datas of the choices (used in models Profil and form ProfilForm):
Boardz = (
('Reddit', 'reddit.com'),
('Discord', 'discord.com'),
('Twitter', 'twitter.com'),
)
Skillz = (
('Python', 'PythonDjango'),
('Rust', 'RustRocket'),
('Ruby', 'RubyOnRails'),
)
Now the concern problem is views.py and my template.html
<!-- this is what I want with my datas -->
<select multiple class="form-control" id="id_board">
<option>reddit.com</option>
<option>discord.com</option>
<option>twitter.com</option>
</select>
<select multiple class="form-control" id="id_skillz">
<option>PythonDjango</option>
<option>RustRocket</option>
<option>RubyOnRails</option>
</select>
<input type="submit" value="Save">
Into the views.py (which is surely wrong) :
def GetDatasForRegisterForm(request):
form = ProfilForm()
return render_response(request, "registration/register.html",{'form': form})
template.html :
I'm totally lost for display my data choices in select multiple for the user, please guys, how make ?
Update : It's good, I have what I wanted, here is for your members of stack overflow, my solution :
class ProfilForm(forms.ModelForm):
skill = forms.MultipleChoiceField(widget=forms.SelectMultiple, choices=Skillz) # skillz and boardz into choices.py
board = forms.MultipleChoiceField(widget=forms.SelectMultiple, choices=Boardz)
class Meta:
model = Profil
fields = ('skill', 'board',)
in views.py > form = ProfilForm(), return render..
{% for value,text in form.board.field.choices %}
<option value="{{ value }}">{{ text }}</option>
{% endfor %}
This is how i go about generating my template and views.py when dealing with forms.
First here you have defined your form ProfilForm one quick way to know the html generated in your form when your views look like
def GetDatasForRegisterForm(request):
form = ProfilForm()
return render_response(request, "registration/register.html",{'form': form})
In your templates you can just do
<form method="POST" action="<your_action>">
{{ csrf_token }}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
Now when you render this django will create a basic HTML for you, based on model specified. You can copy the HTML and customize the styling and populate the values by accessing the form field values.
Now you haven't asked about how to save this form. But let me do that anyway.
We are going to handle the form post in the same controller which will look like.
def GetDatasForRegisterForm(request):
form = ProfilForm(request.POST or None)
if request.method == "POST" and form.is_valid():
form.save()
return redirect("/<sucess_page>")
return render_response(request, "registration/register.html",{'form': form})
In the view here, i am loading the form with POST data if it exists and checking if the form is valid in the POST and saving it as well. You can where to lead the page to if it is success or error.

can't set radio button to required in django

I have the following radio button html using django widget tweaks (i do not have to use this library and open to using whatever method works):
{% for choice in seeking_form2.disaster_recovery %}
<div class="radio radio-primary radio-inline">
{{ choice.tag|attr:"required" }}
<label for='{{ seeking_form2.disaster_recovery.auto_id }}_{{ forloop.counter0 }}'>{{ choice.choice_label }}</label>
</div>
{% endfor %}
Which should create radios that look like this:
<input id="id_disaster_recovery" name="disaster_recovery" type="radio" value="2" required>
My model looks like:
BOOL_CHOICES = ((True, 'Yes'), (False, 'No'))
disaster_recovery = models.BooleanField(choices=BOOL_CHOICES, default=False, )
My form looks like:
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
'disaster_recovery': forms.RadioSelect(),
}
I get the error:
'SafeText' object has no attribute 'as_widget'
If i understand your problem correctly, you should be overriding this in the form, rather than at the template, or the models.
class MyModelForm(..):
disaster_recovery = forms.ChoiceField(choices=BOOL_CHOICES, widget=forms.RadioSelect(), required=True) #Default is dropdown
Now, you could simplify your HTML to render the radiobuttons.
Some more context on this can be found here
To add the HTML required attribute, to your existing form, you can do:
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
'disaster_recovery': forms.RadioSelect(attrs={"required": "required"}),
}
Here is the relevant documentation on the custom attributes

How to auto-generate full HTML from a WTForms form

I'm trying to create a simple WTForms-based admin interface for an SQLAlchemy app, using Jinja2 templates.
I've read the docs of WTForms-Alchemy and I understand that it can auto-generate a form from my model just via a few lines of code, like:
class UserForm(ModelForm):
class Meta:
model = User
My problem is that even though I have this form auto-generated, I found no resource anywhere about how can I make it into a functional HTML page. There are a few snippets about rendering errors for fields, as well as some SO answers mentioning macros for rendering whole fields, but I found absolutely no resource about how to generate a full, functional form automatically.
// I understand that this is something what Flask-Admin might do already, I'm not using Flask so this is not a possibility unfortunately.
WTForms leaves it up to you to figure out how to you want to render out your form after you pass it into your template. The simplest way to render a form would be to just iterate through your form and render the fields. When a field (or its label) is called, it emits HTML.
<form action="/some_url" method="POST">
{% for field in form %}
{{ field.label() }}
{{ field() }}
{% endfor %}
<button type="submit" />
</form>
The macros provided here provide an automated way to generate HTML surrounding these fields.
You can use wtf.quick_form like this, in which case you'll have a totally generic form template. Mark up your db.Model members with info{} properties to set field display names etc
<form method="post" action="/{{route}}">
<fieldset>
{{ wtf.quick_form(form, button_map={'submit':'success'}) }}
<input class="btn btn-success" type="submit" value="Submit" />
<button type="button" class="btn">Cancel</button>
</fieldset>
</form>
Your form definition:
class MyobjectForm(BaseModelForm):
class Meta:
model = Myobject
Then your route handler looks like this:
#app.route('/myobject', methods=('GET', 'POST'))
def myobject_route():
obj = Myobject()
form = MyobjectForm(obj = obj)
if form.validate_on_submit():
form.populate_obj(obj)
db.session.add(obj)
db.session.commit()
return redirect(url_for('index'))
return render_template('form.j2', form=form, title='My Object', route='myobject')

Django form EmailField doesn't accept the css attribute

I have a from containing some fields, but my css class applies to all the fileds except the EmailField. I've also tried sender.widget.attrs.update({'class':"contatct-form"}) and it still doesn't work (just change the size of field). Does anybody knows what the problem is? as all of my searches were unsuccessful.
form:
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(initial='Your name', max_length=100)
sender = forms.EmailField()
#sender.widget.attrs.update({'class':"contatct-form"})
message = forms.CharField(widget=forms.Textarea)
template:
<div class="contatct-form">
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="send" />
</form>
</div>
The problem you have probably is because you have not assigned any widget to your EmailField(), change to this (like #Todor said) should work:
...
sender = forms.EmailField(
widget=forms.EmailInput(attrs={'class': 'contatct-form'})
)
If this doesn't work for whatever reason (probably wrong css styling), you can just change the styling in your css/class directly like so:
div.contatct-form form input[type=email] {
/* your changes here... */
}
Hope this helps.
We have to do that in the init method for one field or all fields with for loop.
class NameForm(forms.Form):
def __init__(*args, **kwargs):
super(NameForm, self).__init__(*args, **kwargs)
self.fields['sender'].widget.attrs.update({'class':"contatct-form"})

How to customize the appearance of the Django-Userena change password form

I am using Django Userena for the first time.So can not able to customize the appearance of the change password form,as we know that userena used the default change password form from django.contrib.auth.forms (if i am not wrong).Now this is becoming tough for me to customize the appearance of the change password form template cause in the change password template, each and every field is rendered as {{ form.as_p }} like that
<form action = "" method="post" role = "form">
<fieldset>
<legend>{% trans "Change Password" %}</legend>
{% csrf_token %}
{{ form.as_p }}
</fieldset>
<input type="submit" value="{% trans "Change password" %}" class="btn btn-success" />
</form>
in mention,i have already been able to format the appearance of other forms provided by userena.for example i have changed the appearance of the Edit Profile form by adding css classes in the forms.py like that
class EditProfileForm(forms.ModelForm):
""" Base form used for fields that are always required """
first_name = forms.CharField(label=_(u'First name'),
max_length=30,
widget=forms.TextInput(attrs={'class' : 'form-control'}),
required=False)
last_name = forms.CharField(label=_(u'Last name'),
max_length=30,
widget=forms.TextInput(attrs={'class' : 'form-control'}),
required=False)
background = forms.CharField(label=(u'Background'),
max_length=500,
widget=forms.Textarea(attrs={'class' : 'form-control'}),
required=True)
and worked, change password form has been rendered from django.contrib.auth.forms,so i don't know how to add css classes in each field of that that file as it is a core file of Django.May be there alternative way to do this ,but i am inexperience in django and also the django userena,i don't know how do this.
It's too late, but for the new visitors,
you can create a new form in your forms.py as
# forms.py
from django.contrib.auth.forms import PasswordChangeForm
...
class MyPasswordChangeForm(PasswordChangeForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["old_password"].widget = forms.PasswordInput(attrs={"class": "form-control"})
self.fields["new_password1"].widget = forms.PasswordInput(attrs={"class": "form-control"})
self.fields["new_password2"].widget = forms.PasswordInput(attrs={"class": "form-control"})
# other customization
and in your views.py you could use PasswordChangeView with your form as
# views.py
...
from django.contrib.auth.views import PasswordChangeView
from .forms import MyPasswordChangeForm
...
class ChangePasswordView(PasswordChangeView):
form_class = MyPasswordChangeForm
template_name = "path/to/your/template.html"
That's all.
You actually need to override the userena view altogether because it passes its own form in the view
urls.py:
# Change password
url(r'^(?P<username>[\#\.\w-]+)/password/$',
accounts.views.my_own_password_change_view,
name='userena_password_change'),
In your views.py:
#secure_required
#permission_required_or_403('change_user', (get_user_model(), 'username', 'username'))
def my_own_password_change_view(request, username, template_name='userena/password_form.html',
pass_form=YourPasswordChangeForm, success_url=None, extra_context=None):
""" Change password of user.
This view is almost a mirror of the view supplied in
:func:`contrib.auth.views.password_change`, with the minor change that in
this view we also use the username to change the password. This was needed
to keep our URLs logical (and REST) across the entire application. And
that in a later stadium administrators can also change the users password
through the web application itself.
:param username:
String supplying the username of the user who's password is about to be
changed.
:param template_name:
String of the name of the template that is used to display the password
change form. Defaults to ``userena/password_form.html``.
:param pass_form:
Form used to change password. Default is the form supplied by Django
itself named ``PasswordChangeForm``.
:param success_url:
Named URL that is passed onto a :func:`reverse` function with
``username`` of the active user. Defaults to the
``userena_password_complete`` URL.
:param extra_context:
Dictionary of extra variables that are passed on to the template. The
``form`` key is always used by the form supplied by ``pass_form``.
**Context**
``form``
Form used to change the password.
"""
user = get_object_or_404(get_user_model(),
username__iexact=username)
form = pass_form(user=user)
if request.method == "POST":
form = pass_form(user=user, data=request.POST)
if form.is_valid():
form.save()
# Send a signal that the password has changed
userena_signals.password_complete.send(sender=None,
user=user)
if success_url: redirect_to = success_url
else: redirect_to = reverse('userena_password_change_complete',
kwargs={'username': user.username})
return redirect(redirect_to)
if not extra_context: extra_context = dict()
extra_context['form'] = form
extra_context['profile'] = get_user_profile(user=user)
return ExtraContextTemplateView.as_view(template_name=template_name,
extra_context=extra_context)(request)
And finally
class YourPasswordChangeForm(forms.ModelForm):
""" Base form used for fields that are always required """
first_name = forms.CharField(label=_(u'First name'),
max_length=30,
widget=forms.TextInput(attrs={'class' : 'form-control'}),
required=False)
last_name = forms.CharField(label=_(u'Last name'),
max_length=30,
widget=forms.TextInput(attrs={'class' : 'form-control'}),
required=False)
background = forms.CharField(label=(u'Background'),
max_length=500,
widget=forms.Textarea(attrs={'class' : 'form-control'}),
required=True)
do even more customization on the html template
<form action="" method="post" id="password_change_form">
{% csrf_token %}
{% for field in form %}
<div class="profile-input w33">
<div class="profile-label" for="{{ field.name }}">{{ field.label }}</div>
{{ field }}
{{ field.errors }}
</div>
{% endfor %}
<div class="profile-input w33">
<input type="submit" class="input updatebtn" value="{% trans "UPDATE" %}"/>
</div>
</form>
If you are going to use Bootstrap and jQuery you can also customize all templates in your userena base file with jQuery.
In my case it saved me a lot of messy code in multiple files across the project.
Just change the desired parts with jQuery or pure JS and CSS for example:
$( "input" ).addClass( "form-control" );

Categories