When I use form.as_p to display my form and, for example, I click on Submit button without fill any field, it shows error messages asking me to fill the required fields. However, when I customize the output of my html template, it doesn't validate the fields and doesn't show any error message. My forms.py:
# forms.py
class SignUpForm(forms.ModelForm):
username = forms.CharField(label='Username', max_length=75, widget=forms.TextInput(attrs={'placeholder' : 'Username'}))
email = forms.EmailField(label='Email', max_length=255)
first_name = forms.CharField(label='First Name', max_length=75)
last_name = forms.CharField(label='Last Name', max_length=75)
birthday = forms.DateField(label='Birthday')
gender = forms.ChoiceField(choices = User.GENDER_CHOICES)
class Meta:
model = User
fields = ['username', 'password', 'email', 'first_name', 'last_name', 'birthday', 'gender']
widgets = {
'password': forms.PasswordInput(attrs={'class': 'form-control'}),
'email': forms.EmailInput(attrs={'class': 'form-control'}),
'birthday': forms.DateInput(attrs={'class': 'form-control'}),
}
def save(self, commit=True):
user = super(SignUpForm, self).save(commit=False)
user.username = self.cleaned_data['username']
user.set_password(self.cleaned_data['password'])
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.birthday = self.cleaned_data['birthday']
user.gender = self.cleaned_data['gender']
if commit:
user.save()
return user
My HTML template is like this:
# registration.html
<form class="form-signin" action="/register/" method="post">
<h2 class="form-signin-heading">registration now</h2>
<div class="login-wrap">
<p>Enter your personal details below</p>
<input type="text" class="form-control" placeholder="{{ form.first_name.label }}" name="{{ form.first_name.name }}" id="id_{{ form.first_name.name }}" maxlength="75" autofocus>
<input type="text" class="form-control" placeholder="{{ form.last_name.label }}" name="{{ form.last_name.name }}" id="id_{{ form.last_name.name }}" maxlength="75" autofocus>
<input type="text" class="form-control" placeholder="{{ form.email.label }}" name="{{ form.email.name }}" id="id_{{ form.email.name }}" maxlength="255" autofocus>
<div class="radios">
{% for choice in form.gender.field.choices %}
<label class="label_radio col-lg-4 col-sm-4" for="">
<input name="{{ form.gender.name }}" id="radio-01" value="{{choice.0}}" type="radio" checked /> {{ choice.1 }}
</label>
{% endfor %}
</div>
<p> Enter your account details below</p>
<input type="text" class="form-control" placeholder="{{ form.username.label }}" name="{{ form.username.name }}" id="id_{{ form.username.name }}" autofocus>
<input type="password" class="form-control" placeholder="{{ form.password.label }}" name="{{ form.password.name }}" id="id_{{ form.password.name }}">
<label class="checkbox">
<input type="checkbox" value="agree this condition"> I agree to the Terms of Service and Privacy Policy
</label>
<input class="btn btn-lg btn-login btn-block" type="submit" value="Submit"/>
<div class="registration">
Already Registered.
<a class="" href="login.html">
Login
</a>
</div>
</div>
</form>
I'm starting now with Django, I read the documentation about custom forms, but I didn't find nothing about how to validate fields as forms.as_p does.
That is the wrong way to produce custom HTML for your form. You should still use the Django form fields - {{ form.first_name }} etc - rather than creating HTML versions yourself and populating them.
However, the issue is simpler than that: you have forgotten to add the {{ form.myfield.errors }} for each field, and the {{ form.non_field_errors }} at the top of the form.
Also note there's no reason to do all that extra work in save. All of those fields are already being set by the superclass: the only thing you need to take care of manually is user.set_password.
Related
I want to display a particular data record from the database of a person who is logged in to the website. I have a default primary key in the migration. Other than that I don't have any of the primary or foreign keys. Below is the models.py and template codes.
models.py
class Ticket(models.Model):
Email = models.CharField(max_length=40)
to = models.CharField(max_length=40)
cc = models.CharField(max_length=50)
subject = models.CharField(max_length=25)
class Meta:
db_table = 'ticket'
def __str__(self):
return self.Email
Following is the views which I had used before, that display's the whole data from the database.
Views.py
def ticket(request):
ticket = Ticket.objects.all()
return render(request, 'web/ticket.html', {'ticket':ticket})
But I want to display data of the respective mail id
ticket.html
{% for ticket in ticket %}
<fieldset id="first">
<label for="From"><b>From</b></label>
<input type="text" id="From" name="From" style="width:100%" value="{{ ticket.Email }}" required> <br> <br>
<label for="To"><b>To</b></label>
<input type="text" id="To" name="To" style="width:100%" value="{{ ticket.to }}" required><br> <br>
<label for="Cc"><b>Cc</b></label>
<input type="text" id="Cc" name="Cc" style="width:100%" value="{{ ticket.cc }}" required><br> <br>
<label for="Subject"><b>Subject</b></label>
<input type="text" id="Subject" name="Subject" style="width:100%" value="{{ ticket.subject }}" required><br> <br>
</fieldset>
{% endfor %}
Thanking you in advance. You will be highly appreciated if you could explain the needful code.
I am trying to save "Contact Us" on my page to a PostgreSQL.
Here is my model:
from django.db import models
from datetime import datetime
# Create your models here.
class Contact(models.Model):
fullname = models.CharField(max_length=200)
email = models.CharField(max_length=50)
message = models.TextField(blank=False)
contact_date = models.DateTimeField(default=datetime.now, blank=False)
user_id = models.IntegerField(blank=True)
def __str__(self):
return self.fullname
Here is my view:
def contact(request):
if request.method == 'POST':
fullname = request.POST['fullname']
email = request.POST.get('email')
message = request.POST.get('message')
contact_date = request.POST.get('contact_date')
user_id = request.POST['user_id']
contact = Contact(fullname=fullname, message=message, email=email, contact_date=contact_date, user_id=user_id)
contact.save()
messages.success(request, 'You have succesfully submitted your message. We will be in touch with you shortly')
return redirect('index')
This is the error I am getting
null value in column "email" violates not-null constraint
DETAIL: Failing row contains (1, Great job guys!, null, null, null, 9).
I typed Great job guys into the drop message field.
This is how the HTML looks like
<form class="containerForm" action="{% url 'contact'%}" method="POST">
{% csrf_token %}
{% if user.is_authenticated %}
<input type="hidden" name="user_id" value={{user.id}}>
{% else %}
<input type="hidden" name="user_id" value="0">
{% endif %}
<input type="text" name="fullname" id="fullname" class="form-control" placeholder="Full Name">
<input type="text" name="fullname" id="email" class="form-control" placeholder="Email Address">
<input type="text" name="fullname" id="message" class="form-control" placeholder="Drop A Message">
<input type="submit" value="Send A Message">
</form>
Kindly help. I have spent some hours on this.
You have the same input names for fullname, email, message.
Try this HTML
<form class="containerForm" action="{% url 'contact'%}" method="POST">
{% csrf_token %}
{% if user.is_authenticated %}
<input type="hidden" name="user_id" value={{user.id}}>
{% else %}
<input type="hidden" name="user_id" value="0">
{% endif %}
<input type="text" name="fullname" id="fullname" class="form-control" placeholder="Full Name">
<input type="text" name="email" id="email" class="form-control" placeholder="Email Address">
<input type="text" name="message" id="message" class="form-control" placeholder="Drop A Message">
<input type="submit" value="Send A Message">
</form>
I am editing the Firtname and Lastname fetched from auth_User. When I edit the name and save, the None value is passed to the names. On verifying page source I dont see any error.
form.py
from django.contrib.auth.models import User
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name','last_name', 'email')
view.py
def edit(request):
if request.method == 'POST':
user_form = UserEditForm(instance=request.user,
data=request.POST)
if user_form.is_valid():
user_form.save()
messages.success(request, 'Profile updated successfully!')
else:
messages.success(request, 'Error updating your profile!')
else:
user_form = UserEditForm(instance=request.user)
return render(request,
'account/edit.html',
{'user_form': user_form})
HTML
<div class="form-row">
<label class="col-sm-2 control-label" placeholder="First Name">First Name:</label>
<div class="col-sm-4">
<input type="text" class="form-control" id="first_name" value="{{ user_form.first_name.value }}">
</div>
<label class="col-sm-2 control-label">Last Name:</label>
<div class="col-sm-4">
<input type="text" class="form-control" id="last_name" value="{{ user_form.last_name.value }}">
</div>
</div>
<div class="form-row">
<label for="email" class="col-sm-2 control-label">Email address:</label>{{ user_form.email }}
<div class="col-sm-4">
<input type="email" class="form-control" id="email" value="{{ user_form.email.value }}">
</div>
</div>
You do not have any name attributes on your form fields, so no data will be submitted. Add a name attribute to both fields:
<input name="first_name" type="text" class="form-control" id="first_name" value="{{ user_form.first_name.value }}" >
<!-- ^^^^ note new name attribute -->
and:
<input name="last_name" type="text" class="form-control" id="last_name" value="{{ user_form.last_name.value }}" >
Note also that you have specified email in the fields on your form, but there is no email field in your HTML, which will also cause problems. You should either add that field to your HTML or remove it from the form definition.
You might also consider using Django's form helpers to render the fields.
The <input> tags you have created in your template do not include name attributes. When you attempt to submit the form, these items will not be sent.
The correct name for each form field can be accessed using the html_name attribute, eg:
{{ user_form.first_name.html_name }}
#solarissmoke mentioned that you should consider using the Django form helpers, and I strongly agree. If you don't like how default widgets appear in your HTML, you can add classes when you create the form:
from django.contrib.auth.models import User
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name','last_name', 'email')
widgets = {
'first_name': forms.TextInput(attrs={'class': 'form-control'}),
'last_name': forms.TextInput(attrs={'class': 'form-control'}),
'email': forms.EmailInput(attrs={'class': 'form-control'}),
}
Then in your template:
<div class="form-row">
<label for="{{ user_form.first_name.auto_id }}" class="col-sm-2 control-label" placeholder="First Name">First Name:</label>
<div class="col-sm-4">
{{ user_form.first_name }}
</div>
<label for="{{ user_form.last_name.auto_id }}" class="col-sm-2 control-label">Last Name:</label>
<div class="col-sm-4">
{{ user_form.last_name }}
</div>
</div>
<div class="form-row">
<label for="{{ user_form.email.auto_id }}" class="col-sm-2 control-label">Email address:</label>
<div class="col-sm-4">
{{ user_form.email }}
</div>
</div>
I know my code is not optimal as I'm only a beginner with Django so don't be too hard on me
Here is my code :
views.py
class ComposantUpdate(UpdateView):
model = configuration
fields = '__all__'
template_name = 'accueil/exploitation/update_composant.html'
update_composant.html
<form action="{% url 'composant_update' pk=composant.id %}" method="post">
{% csrf_token %}
<div class="form-group">
{% for field in form %}
<label class="col-md-6 offset-md-3 nom_champ"> {{field.label_tag}}</label>
<input class="col-md-4 offset-md-4 contenu_champ" type="text" name="{{ field.label }}" id="{{ field.id_for_label }}" value="{{ field.value }}"/>
{%endfor%}
<br>
<br>
<button class="col-md-6 offset-md-3 btn btn-primary" type="submit" value="Update" /> Mettre à jour </button>
</div>
</form>
urls.py
path('update_composant/<int:pk>', views.ComposantUpdate.as_view(),
name='composant_update'),
models.py
class configuration(models.Model):
Num_ordre = models.CharField(max_length=15)
Composant = models.CharField(max_length=15)
Designation = models.CharField(max_length=15)
Qte_servie = models.IntegerField()
Qte_a_servir = models.IntegerField()
Lot = models.CharField(max_length=15)
Categorie = models.CharField(max_length=15)
Famille = models.CharField(max_length=15)
def __str__(self):
return '%s %s %s' % (self.Num_ordre, self.Designation, self.Lot)
when I go to the url of the form, all the fields get the content of the database which is what I expect but if I modify the "Lot" field and click to submit, my database is not updated at all with the new value of "Lot". DO you have any idea of why ? For information, I do get redirected to the 'composant_update' view and no error is risen
In fact, I didn't write my html correctly, the attribute "name" in the input should have been {{field.html_name}} instead of {{field.label}}.
This doesn't work :
<input class="col-md-4 offset-md-4 contenu_champ" type="text" name="{{ field.label }}" id="{{ field.id_for_label }}" value="{{ field.value }}"/>
This works :
<input class="col-md-4 offset-md-4 contenu_champ" type="text" name="{{ field.html_name}}" id="{{ field.id_for_label }}" value="{{ field.value }}"/>
See https://docs.djangoproject.com/en/2.0/topics/forms/#s-looping-over-the-form-s-fields for more information
Thanks Willem Van Onsem !
When I go to my "edit profile" page this is what it looks like:
So it shows me the algorithm, iterations and hash. And if I want to remove it form my forms.py (remove password):
class EditProfileForm(UserChangeForm):
template_name='/something/else'
class Meta:
model = User
fields = (
'email',
'first_name',
'last_name',
**'password'**
)
It shows me this:
Feel free to share your ideas.
I changed my code form forms.py to an editable code in edit_profile.html (that takes the entries form forms.py):
edit_profile.html:
<form method="post">
{% csrf_token %}
<label for="first_name">Vorname </label>
<input style="margin-bottom: 1em;" id="first_name" class="form-control" type="text" maxlength="25" name="first_name" value="{{ user.first_name }}"><br>
<label for="last_name">Nachname </label>
<input style=" margin-bottom: 1em;" id="last_name" class="form-control" type="text" maxlength="25" name="last_name" value="{{ user.last_name }}"><br>
<label for="email">E-Mail </label>
<input style="margin-bottom: 1em;" id="email" class="form-control" type="email" maxlength="50" required=True unique=True name="email" value="{{ user.email }}"><br>
<button class="btn btn-success btn-sm" type="submit">Bestätigen</button>
<a style="margin-left: 1em;" href="{% url 'accounts:view_profile' %}" id="cancel" name="cancel" class="btn btn-default">Zurück</button></a>
{% if form.errors %}
<p style="margin-left: 5em;" class=" label label-danger">
Das ist keine gültige E-Mail-Adresse. Bitte versuche Sie es erneut.
</p>
{% endif %}
</form>