How can I show error messages in change_password in Django - django

I'm struggling to show error message in change_password in Django.
I tried all the ways I know to show errors in the template file, but nothing shows up when I put some wrong information on purpose.
I thought it's because of redirecting when the form is not valid. But, the changing password feature doesn't work without the redirecting.
Can anyone suggest a way to do that?
views.py
def change_password(request):
if request.method == 'POST':
form = PasswordChangeForm(data=request.POST, user=request.user)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
return redirect('/accounts/profile')
else:
return redirect('/accounts/change-password')
else:
form = PasswordChangeForm(user=request.user)
args = {'form': form}
return render(request, 'accounts/change_password.html', args)
HTML template
<form method="POST">
{% csrf_token %}
<p class="error-message">
{{ form.errors.old_password }}
{{ form.errors.new_password1 }}
{{ form.errors.new_password2 }}
{{ form.non_field_errors }}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
{% endif %}
</p>
<div class="form-group row">
<label for="inputPassword" class="col-sm-3 col-form-label">Old Password</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="old_password" placeholder="Old Password" required autofocus>
</div>
</div>
<div class="form-group row">
<label for="inputPassword" class="col-sm-3 col-form-label">New Password</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="new_password1" placeholder="New Password" required>
</div>
</div>
<div class="form-group row">
<label for="inputPassword" class="col-sm-3 col-form-label">Confirm New Password</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="new_password2" id="inputPassword" placeholder="Confirm New Password" required>
</div>
</div>
<input class="btn btn-modvisor btn-block" type="submit" name="" value="Submit">
</form>

Try without redirecting when there is an error, like this:
def change_password(request):
if request.method == 'POST':
form = PasswordChangeForm(data=request.POST, user=request.user)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
return redirect('/accounts/profile')
else:
form = PasswordChangeForm(user=request.user)
args = {'form': form}
return render(request, 'accounts/change_password.html', args)
As you can see, like this the line return render(... is also called when the form is not valid.

Related

Django SetPasswordForm doesn't render anything

Django's SetPasswordForm doesn't render anything, please help.
This is what I got:
views.py
from django.contrib.auth.forms import SetPasswordForm
#login_required
def profile_security(request):
template = "profiles/profile_security.html"
form = SetPasswordForm
print("form.base_fields: %s" % form.base_fields)
context = {"profile_index_active": "active", "underline_security": "text-underline", "form": form}
return render(request, template, context)
html
<form method="post">{% csrf_token %}
{{ form.as_p }}
</form>
tried this html as well
<form method="post">{% csrf_token %}
<div class="form-group field-password1">
{{ form.new_password1.errors }}
<label for="id_new_password1">New Password</label>
{{ form.new_password1 }}
</div>
<div class="form-group field-password2">
{{ form.new_password2.errors }}
<label for="id_new_password2">Repeat New Password</label>
{{ form.new_password2 }}
</div>
<div class="form-group">
<input class="btn btn-success text-uppercase w-100" type="submit" value="Guardar nueva contraseña">
</div>
</form>
It does print the fields correctly:
form.base_fields: {'new_password1': <django.forms.fields.CharField object at 0x7f49174e2790>, 'new_password2': <django.forms.fields.CharField object at 0x7f49174e2940>}
but it doesn't render anything. What am I doing wrong?
SetPasswordForm class needs user instance
form = SetPasswordForm(request.user)

display multiple django messages in one page?

I have a template in which user can change his details like name, email and password. I am getting wrong messages after updating info ( if I change the password then I got message "Invalid" that is part of edit_profile) though I used extra_tags for message to identify two different messages,
But still having issue. I tried searching a lot, and found some relevant questions but was not helpful.
views.py
def edit_profile(request):
if request.user.is_authenticated:
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
messages.success(request, "Update successful!", extra_tags='edit_profile')
return redirect("accounts:edit_profile")
else:
messages.error(request, "Invalid", extra_tags='edit_profile')
return redirect("accounts:edit_profile")
else:
form = EditProfileForm(instance=request.user)
return render(request, "accounts/edit_profile.html", {'form': form})
else:
redirect('accounts:signin')
def change_password(request):
if request.method == 'POST':
form = PasswordChangeForm(data=request.POST, user=request.user)
if form.is_valid():
form.save()
messages.success(request, "Update successful!", extra_tags='change_password')
update_session_auth_hash(request, form.user)
return redirect("accounts:change_password")
else:
messages.error(request, "Password Error", extra_tags='change_password')
return redirect("accounts:change_password")
else:
form = PasswordChangeForm(user=request.user)
return render(request, "accounts/edit_profile.html", {'form': form})
template
<h2 class="font-weight-bolder">Account Details</h2>
<!-- edit_profile form -->
<form action="{% url 'accounts:edit_profile' %}" method="post" class="row g-3 needs-validation"
novalidate>
{% csrf_token %}
<!-- 1 Username -->
<div class="offset-md-2 col-md-4 ">
<label for="username" class="form-label">Username</label><br>
<input type="text" name="username" class="form-control" id="username"
value="{{ form.username.value }}" required>
<div class="invalid-feedback">
Please provide name.
</div>
</div>
<!-- 2 Email -->
<div class="offset-md-1 col-md-4">
<label for="email" class="form-label">Email</label>
<input type="email" name="email" class="form-control" id="email"
value="{{ form.email.value }}" required>
<div class="invalid-feedback">
Please provide a valid email.
</div>
</div>
{% for message in messages %}
{% if 'edit_profile' in message.tags %}
<div class="offset-md-2 col-md-6 pt-2">
<h4 class="text-success font-weight-bolder">{{ message }}</h4>
</div>
{% endif %}
{% endfor %}
<div class="offset-md-2 col-md-4 pt-2 pb-2">
<input type="submit" value="Save" class="btn btn-outline-primary btn-lg">
</div>
</form>
<!-- Password section -->
<div class="offset-md-2 pt-3 pb-2">
<h4 class="font-weight-bold">Password</h4>
</div>
<form action="{% url 'accounts:change_password' %}" method="post" class="row g-3 needs-validation"
novalidate>
{% csrf_token %}
<div class="offset-md-2 col-md-3">
<label for="old_password" class="form-label">Current password</label>
<input type="password" name="old_password" value="" class="form-control" id="old_password" required>
<div class="invalid-feedback">
Please provide a valid password.
</div>
</div>
<div class="col-md-3">
<label for="new_password1" class="form-label">New password</label>
<input type="password" name="new_password1" value="" class="form-control" id="new_password1"
required>
<div class="invalid-feedback">
Please provide a valid password.
</div>
</div>
<div class="col-md-3">
<label for="new_password2" class="form-label">Confirm password</label>
<input type="password" name="new_password2" value="" class="form-control" id="new_password2"
required>
<div class="invalid-feedback">
Please provide a valid password.
</div>
</div>
{% for message in messages %}
{% if "change_password" in message %}
<div class="offset-md-2 col-md-6 pt-2">
<h4 class="text-success font-weight-bolder">{{ message }}</h4>
</div>
{% endif %}
{% endfor %}
<div class="offset-md-2 col-md-4 pt-2">
<input type="submit" value="Change Password" class="btn btn-outline-primary btn-lg">
</div>
</form>

I don't understand why my form is not validating in django

I am still new to django. Playing around with a leadmanager app and I don't know why my form is not validating.
views
def index(request):
lead=LeadForm()
if request.method == 'POST':
lead=LeadForm(request.POST)
if lead.is_valid():
messages.success(request, f'Thank you for registering. Someone will be contacting you soon.')
return redirect('index')
else:
lead=LeadForm()
messages.error(request, f'Something went wrong. Please try again later.')
return render(request, "frontend/index.html", {'lead':lead})
in index.html
<form action="" method="POST" class="lead-form">
{% csrf_token %}
<fieldset class="lead-info">
<div class="form-control">
<label for="">Full Name</label>
{{ lead.fullname }}
</div>
<div class="form-control">
<label for="">Email</label>
{{ lead.email }}
</div>
<div class="form-control">
<label for="">Phone</label>
{{ lead.phone }}
</div>
<div class="form-control">
<label for="">City</label>
{{ lead.city }}
</div>
</fieldset>
<button type="submit" class="btn-pill">Submit</button>
</form>
in forms.py
class LeadForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = Lead
fields = ['fullname', 'email', 'phone', 'city', 'contact_preference']
widgets = {'contact_preference': forms.RadioSelect }
Any help is appreciated. contact_preference is rendering FYI, I just cut the code to keep this question not that long.

can't raise ValidationError django validators

I need to know how I raise ValidationError of a validators in django.
First I tried the methode on form in simple page and forms and it works perfectly.
but the problems appear when I use modal fade class in a page works with pk
for example(127.0.0.1:8000/wsheets/AMA2/).
the message is
(The view Home.views.wellsets didn't return an HttpResponse object. It returned None instead.)
and mt views.wellsets is
def wellsets(request, WeelN):
serchedWl = WellSheets.objects.filter(WellID__exact=WeelN)
form= WelshetForm()
context ={
'title': 'SearchWS',
'Wellslistsh':serchedWl,
'WeelN':WeelN,
'form':form,
}
if request.method == 'POST':
form =WelshetForm(request.POST, request.FILES)
if form.is_valid():
form.instance.author = request.user
form.save()
return redirect('WellSheetg', WeelN)
else:
return render(request,'Home/WELLINFO/W_TchD/wellshts.html', context)
and my form + validator is:
from django.core.exceptions import ValidationError
class WelshetForm(forms.ModelForm):
WellID = forms.CharField(label='Well Name',max_length=15)
FileNm = forms.CharField(label='File Name',max_length=15)
def clean_SHRPath(self):
SHRPath = self.cleaned_data.get('SHRPath')
size= SHRPath._size
if SHRPath._size > 1024*1024*10:
raise forms.ValidationError('Size is bigger than allowed')
return SHRPath
and at last this is my html form
<button type="button" class="btn button1 btn-outline-success mb-2 btn-block" data-toggle="modal" data-target="#myModal" >
<p class="thicker">Add new Well-Sheet</p></button>
<div class="modal fade" id="myModal" role="dialog" >
<div class="modal-dialog ">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title"><p class="thicker">Upload Well-sheet</p></h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<p class="thicker">Check your file before uploading ({{WeelN}})</p>
<div class="w3-panel w3-light-grey w3-round-large solid"">
<form method="POST" id="formOne" enctype= multipart/form-data>
{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-6 mb-0">
{{ form.WellID|as_crispy_field }} </div></div>
<div class="form-row">
<div class="form-group col-md-8 mb-0">
{{ form.SHRPath }}</div></div>
<p style="color:red;">Maximum upload size is 10Mb</p>
<br>
<input class="btn btn-success mb-6" name="form_uplod" type="submit" value="AddSheet">
</form>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button></div>
</div>
</div>
Modal form
As #IainShelvington said, you need to remove else block to get a response. You can try like this:
def wellsets(request, WeelN):
serchedWl = WellSheets.objects.filter(WellID__exact=WeelN)
form= WelshetForm()
if request.method == 'POST':
form =WelshetForm(request.POST, request.FILES)
if form.is_valid():
form.instance.author = request.user
form.save()
return redirect('WellSheetg', WeelN)
context ={
'title': 'SearchWS',
'Wellslistsh':serchedWl,
'WeelN':WeelN,
'form':form,
}
return render(request,'Home/WELLINFO/W_TchD/wellshts.html', context)
So that, even if the validation fails, you will get a response with form containing error data. To show form errors in template, try like this:
<div class="form-group col-md-8 mb-0">
{{ form.SHRPath }}</div>
{% if form.SHRPath.errors|length > 0 %}
<p style="color:red;">{{ form.SHRPath.errors.0 }}</p>
<br>
{% endfor %}
More information can be found in documenation.
Hi In fact I did it by other way
no error message appear in the bootstrap modal at the moment of submitting but it works fine.
in my views.py I created a new form (form_error):
def wellsets(request, WeelN):
serchedWl = WellSheets.objects.filter(WellID__exact=WeelN)
form= WelshetForm()
form_error = False
if request.method == 'POST':
form =WelshetForm(request.POST, request.FILES)
if form.is_valid():
form.instance.author = request.user
form.save()
return redirect('WellSheetg', WeelN)
else:
form_error = 'Check your file Name, type and size <10Mb'
context ={
'title': 'SearchWS',
'Wellslistsh':serchedWl,
'WeelN':WeelN,
'form':form,
'form_error': form_error,
}
return render(request,'Home/WELLINFO/W_TchD/wellshts.html', context)
and in my Html :
{% if form %}
<div class="w3-panel w3-light-grey w3-round-large solid"">
<form method="POST" id="formOne" enctype= multipart/form-data>
{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-6 mb-0">
{{ form.WellID|as_crispy_field }}</div></div>
{% if form_error %}
<li style="color:red;"><strong>Check the Well if it does exist</strong></li>
{% endif %}
<div class="form-row">
<div class="form-group col-md-6 mb-0">
{{ form.FileNm|as_crispy_field }}</div></div>
<div class="form-row">
<div class="form-group col-md-6 mb-0">
{{ form.Folio|as_crispy_field }}</div></div>
<div class="form-row">
<div class="form-group col-md-8 mb-0">
{{ form.SHRPath }}</div></div>
{% if form_error %}
<li style="color:red;"><strong>{{form_error}}</strong></li>
<li style="color:red;"><strong>File type (pdf, jpg ,xls..) only accepted</strong></li>
{% endif %}
<p style="color:red;">Maximum upload size is 10Mb</p>
<br>
<input class="btn btn-success mb-6" data-target="#myModal" name="form_uplod" type="submit" value="AddSheet">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</form>
{% endif %}
and I creted a validators.py and in it:
def validate_file_size(value):
filesize= value.size
print('very nice',filesize/(1024*1024))
if filesize > 1024*1024*10:
raise ValidationError(_("The maximum file size that can be uploaded is 10MB"), code='invalid')
return value
def validate_text(value):
from Home.models import Wellinfo
WELDATA= Wellinfo.objects.filter(WellID=value)
print(value, WELDATA)
if Wellinfo.objects.filter(WellID=value).exists():
return value
raise ValidationError("The Well does't exists!")
and at last in the model.py i called the decorator as;
class WellSheets(models.Model):
WellID = models.CharField(max_length=15, validators= [validate_text])
FileNm = models.CharField(max_length=15)
Folio = models.PositiveIntegerField(blank=True, null=True)
SHRPath = models.FileField(upload_to='Well_sheets/', validators= [validate_file_size])
at the end the file will not added or uploaded and when I cambak to my modal window I see that
Description of modal window

form validation fails some times and shows value erorr

Sometimes form is validating but sometimes form is not validating and shows value error
views.py
def hai(request):
if request.method == 'POST':
obj1 = hello(request.FILES, request.POST)
if obj1.is_valid():
return HttpResponse("success")
does form need to be cleaned every time submiting?
forms.py
class hello(forms.Form):
uname = forms.CharField(max_length=100)
img = forms.FileField()
template
<html>
<head></head>
<body>
<form action= {% url 'hai' %} method="POST" enctype="multipart/form-data ">
{% csrf_token %}
<div class="d-flex">
<div class="form-group mr-2">
<label for="" class="label">Pick-up date</label>
<input type="text" name="uname" class="form-control"
placeholder="Date">
</div><br>
<div class="form-group ml-2">
<label for="" class="label">Drop-off date</label>
<input type="file" name="img" class="form-control"
placeholder="Date">
</div><br>
<input type="submit" value="Book Now" class="btn btn-primary py-3 px4">
</div>
</form>
</body>
</html>
This is the error:
The problem here is that you should always return HttpResponse (or subclass), whether yourr form is valid or not; So basically you should have:
def hai(request):
if request.method == 'POST':
obj1 = hello(request.FILES, request.POST)
if obj1.is_valid():
return HttpResponse("success")
else:
return HttpResponse("error")
or you can send back the form with it's errors in the template, if you wish.