django add placeholder text to form field - python

In Django I have the below code which is creating a username and password form on an HTML Page:
<div class="control-group">
{{ form.username }}
</div>
<div class="control-group">
{{ form.password }}
</div>
I want to add "Username" and "Password" placeholder text within the field, and then when the user clicks on the field the word dissapears. What is the best way to achieve this ?

You must use the placeholder properties
class LoginForm(forms.Form):
username = forms.CharField(label='username')
password = forms.CharField(label='password')
def __init__(self, *args, **kwargs):
super(LoginForm, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs['placeholder'] = 'username'
self.fields['password '].widget.attrs['placeholder'] = 'password'
or
class LoginForm(forms.Form):
username = forms.CharField(label='username',widget=forms.TextInput(attrs={'placeholder':'username'}))
password = forms.CharField(label='password',widget=forms.PasswordInput(attrs={'placeholder':'password'}))

In case it might help someone, I wanted to use the help_text property of a model as the placeholder. This is the simplest way I could figure it out, based on aziminia's answer:
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for _, value in self.fields.items():
value.widget.attrs['placeholder'] = value.help_text
class Meta:
model = models.MyModel
fields = (...)

I hope you do have a forms.py file in your project. While creating your form, you can use following to set placeholder for your fields:
username = forms.CharField(label='username',
widget=forms.TextInput(attrs={'placeholder': 'username'}))
If you have ModelForm in your project you can implement as:
class MyForm(forms.ModelForm):
class Meta:
model = User
widgets = {
'username': forms.TextInput(attrs={'placeholder': 'username'}),
..........
}

In case if you want to have field name as a placeholder, you can use code below:
class LoginForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(LoginForm, self).__init__(*args, **kwargs)
for k,v in self.fields.items():
v.widget.attrs['placeholder'] = k.capitalize()
Otherwise please refere to this answer.

Related

Django: One model, different forms and widgets?

I try to find the best way to have a field with multiple content types.
What I've done so far is a Contact model with a contacttype CharField:
class Contact(models.Model):
CONTACT_TYPES = (
('email', 'Email'),
('phone', 'Phone'),
('address', 'Address'),
('facebook', 'Facebook'),
('linkedin', 'LinkedIn'),
('youtube', 'Youtube'),
('twitter', 'Twitter'),
('google', 'Google'),
)
teammember = models.ForeignKey(TeamMember)
description = models.CharField(max_length=100, null=True)
contacttype = models.CharField(max_length=100, choices= CONTACT_TYPES, default='email')
contact = models.TextField()
My goal is to let the user add different contact informations, which'll be listed on the profile page, but with only one model.
I was thinking about a class for each ModelForm:
class ContactForm(ModelForm):
def __init__(self, data, *args, **kwargs):
super(ModelForm, self).__init__(data, *args, **kwargs)
self.contacttype = ""
class Meta:
model = Contact
fields = ['description', 'contact']
widgets = {'contact': TextInput()}
def clean_contacttype(self):
return self.contacttype
class ContactEmailForm(ContactForm):
def __init__(self, data, *args, **kwargs):
super(ContactForm, self).__init__(data, *args, **kwargs)
self.contacttype = "email"
class Meta(ContactForm.Meta):
model = Contact
fields = ['description', 'contact']
widgets = {'contact': EmailInput()}
class ContactPhoneForm(ContactForm):
def __init__(self, data, *args, **kwargs):
super(ContactForm, self).__init__(data, *args, **kwargs)
self.contacttype = "phone"
class Meta(ContactForm.Meta):
model = Contact
fields = ['description', 'contact']
widgets = {'contact': TextInput()}
def clean_contact(self):
cleaned_data = super(ContactForm, self).clean()
contact = cleaned_data.get("contact")
# Perform some phone number validations
return contact
Then, in my view, I would choose the correct form depending on the request argument (ex: /contact/add/email or /contact/add/phone).
I'm trying to find the most elegant way to do this, so any help is welcome.
Thanks for reading.
if you want to use one html file, then this is one of solutions.
class YourView(TemplateView):
template_name = 'your_template.html'
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
if context['type'] == 'phone':
context['form'] = ContactPhoneForm
elif ...
if you set your view, then
<form action="{% url "your view" %}" enctype="multipart/form-data" method="POST">{% csrf_token %}
{% if form.contenttype == 'phone' %}
{% include "partials/contact_phone_form.html" with form=form %}
{% elif form.contenttype == 'email' %}
{% include "partials/contact_email_form.html" with form=form %}
{% else %}
do something.
{% endif %}
</form>
and, contact_phone_form.html and contact_email_form is looks like
anything.
<input name='phone'>
anything.
this solution is for one template, multi form.
if you want to do multi template for specific form, then you can use this.
class YourView(TemplateView):
template_name = 'your_template.html'
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
if context['type'] == 'phone':
template_name = 'phone_form_template.html'
elif context['type'] == 'email':
template_name = 'email_form_template.html'
...
I would use forms.Form depending on the request argument like:
/contact/add/?type=email or /contact/add/?type=phone
and so you can use it like (not tested code):
class ContactForm(forms.Form):
def __init__(self, *args, **kwargs):
super(CreateUserquestionnaireForm, self).__init__(*args, **kwargs)
if "email" in self.data:
... do some thing like change contact type or widget
if "phone" in self.data:
... do some thing like change contact type or widget

Inputs not showing up as required in browser for ModelForm in Django

When I instantiate the following form and use it in my template. My inputs don't show up as required. Anyone have any idea why?
class SampleForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(SampleForm, self).__init__(*args, **kwargs)
# Making name required
self.fields['x'].required = True
self.fields['y'].required = True
self.fields['z'].required = True
self.fields['a'].required = True
class Meta:
model = Sample
fields = ['x','y','z','a' 'email']
Template
<div>
<form>
{{form}}
</form>
</div>
Try use:
{% if field.field.required %}
using this snippet:
snippet

How do I remove Label text in Django generated form?

I have a form that is displaying well only for the label text that I don't want and I have tried all I could to let it off my form but it won't just go...
forms.py:
class sign_up_form(forms.ModelForm):
class Meta:
model = Users
fields =['email']
widgets = {
'email': forms.EmailInput(attrs={
'id': 'email',
'class': 'form-control input-lg emailAddress',
'name': 'email',
'placeholder': 'Enter a valid email'})}
I have tried:
views.py:
from django.shortcuts import render
from mysite.forms import sign_up_form
def register(request):
sign_up = sign_up_form(auto_id=False)
context = {'sign_up_form': sign_up}
return render(request, 'mysite/register.html', context)
I need my widgets as defined above.
In ModelForms there will be default labels so you have to over-ride where you don't need labels
you can define it like this
class sign_up_form(forms.ModelForm):
email = forms.CharField(widget=forms.Textarea, label='')
class Meta:
model = Users
fields =['email']
This method will not include labels for your form, other method depends on rendering in template. You can always avoid labels from form
<label>MY LABEL</label> instead of {{ form.field.label }}
In __init__ method set your field label as empty.This will remove label text.
def __init__(self, *args, **kwargs):
super(sign_up_form, self).__init__(*args, **kwargs)
self.fields['email'].label = ""
If you're wanting to remove all labels, you can use:
class sign_up_form(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for key, field in self.fields.items():
field.label = ""

Django add attribute to every field by default

I need to be pointed in the right direction. I 'Crispy Forms' to render a form I use with AngularJS. I would like to add the attribute ng-model="NAME" to all form fields by default.
I was thinking this could be done using a mixin added to my form i.e. AngularJSFormMixin:
class ProfileAuthenticationForm(AngularJSFormMixin, AuthenticationForm):
def __init__(self, *args, **kwargs):
super(ProfileAuthenticationForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
# turn off HTML5 validation
self.helper.attrs = {'novalidate': ''}
self.helper.form_show_labels = False
self.helper.layout = Layout(
Field('username', placeholder="E-mail", autocomplete='off'),
Field('password', placeholder="Password", autocomplete='off'),
HTML('<input type="submit" name="Login" ng-click="submit()" css_class="btn btn-primary btn-block" />'),
)
but I'm unsure what to do from here with AngularJSFormMixin. Is there a way to auto add ng-model="NAME" to every field by default?
I've never worked with crispy forms before but this is what I have done in the __init__ on my model forms to add a ng-model attribute with a value to it. My 'get-error-elements' directive is used to show errors of the form to the user:
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
for field in self:
field.field.widget.attrs.update({'ng-focus': ''})
field.field.widget.attrs.update({
'ng-model': 'formName.{0}'.format(field.name),
'get-error-elements': '',
})

Django - user rate profile

I am a newbie to Django and this question might be an easy one, but it has already been bothering me for a while.
<form method="post" action="/vote/" class="vote_form">
<input type="hidden" id="id_link" name="user_profile" class="hidden_id" value="5" />
<input type="hidden" id="id_voter" name="voter" class="hidden_id" value="3" />
New Score: <input name="score" class="" value="7" />
<button type="submit">Submit</button>
</form>
urls.py
url(r'^vote/$', auth(VoteFormView.as_view()), name="vote"),
views.py
class VoteFormView(FormView):
form_class = VoteForm
def create_response(self, vdict=dict(), valid_form=True):
response = HttpResponse(json.dumps(vdict))
response.status = 200 if valid_form else 500
return response
def form_valid(self, form):
profile = get_object_or_404(UserProfile, pk=form.data['user_profile'])
user = self.request.user
score = form.cleaned_data['score']
prev_votes = Vote.objects.filter(voter=user, profile=profile)
has_voted = (len(prev_votes) > 0)
ret = {"success": 1, "profile": profile, "voter: ": user}
if not has_voted:
# add vote
v = Vote.objects.create(voter=user, profile=profile, score=score)
ret["voteobj"] = v.id
# else response already ranked
return self.create_response(ret, True)
def form_invalid(self, form):
...do something when form invalid...
forms.py
class VoteForm(forms.ModelForm):
class Meta:
model = Vote
models.py
class Vote(models.Model):
voter = models.ForeignKey(User)
profile = models.ForeignKey(UserProfile)
score = models.FloatField(default=10.0)
def __unicode__(self):
return "%s voted %s" % (self.voter.username, self.profile)
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True)
# Extra attributes
As you can see, I have a simple form with 2 fields: a user_profile (PK of a user profile) and a score. After the form is submitted, it has this error: "form_errors": {"profile": ["This field is required."]} . So it always goes to to form_invalid.
Where am I supposed to get profile object if it is not form_valid?
I tried to redefine VoteForm as below, which does not work either.
class VoteForm(forms.ModelForm):
def clean_profile(self):
profile_pk = self.cleaned_data['profile']
profile = None
try:
profile = UserProfile.objects.get(pk=profile_pk)
except UserProfile.DoesNotExist:
raise forms.ValidationError("User profile doesn't exist.")
return profile
def save(self, *args, **kwargs):
vote = super(VoteForm, self).save(*args, **kwargs)
return vote
class Meta:
model = Vote
Any ideas?
You have to change your hidden input name from user_profile to profile.
Keep in mind this is a poor design since anyone can inject an arbitrary voter id.
Here is how I would do it
class VoteForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop("user")
super(VoteForm, self).__init__(*args, **kwargs)
def save(self, *args, **kwargs):
# manipulate self.user
and then in your view
form = VoteForm(..., user=request.user)
The name of your hidden field is user_profile, but your code refers to it as just profile. Try changing the html of the form so it is named profile.
As an aside you should include the voter id in your form, that should be added in your processing code based on the logged in user. Currently anyone could change the voter hidden field and record a vote for a different user.

Categories

Resources