Django SetPasswordForm doesn't render anything - django

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)

Related

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.

Django contact form doesnt submit

I am trying to set up a contact form. I have implemented the Django-crispy-forms and now my form is not submitted (I don't have any errors).
I've added action="" to my form in my template without any success.
forms.py
class ContactForm(forms.Form):
name = forms.CharField(max_length=100, help_text='Enter your name or username')
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea(attrs={'rows': 3, 'cols': 40}), help_text='Example: I forgot my password!')
views.py
def contact_us(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
sender_name = form.cleaned_data['name']
sender_email = form.cleaned_data['email']
message = "From {0}:\n\n{1}".format(sender_name, form.cleaned_data['message'])
send_mail('PLM_Tool contact', message, sender_email, ['myadress#gmail.com'])
return redirect('home:index')
else:
form = ContactForm()
return render(request, 'accounts/contact.html', {'form': form})
urls.py
app_name = 'accounts'
urlpatterns = [path('contact/', views.contact_us, name='contact'),]
contact.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block main %}
<form method="post" action="">
{% csrf_token %}
<div class="row">
<div class="col-6">
{{ form.name|as_crispy_field }}
</div>
<div class="col-6">
{{ form.email|as_crispy_field }}
</div>
<div class="col-6">
{{ form.message|as_crispy_field }}
</div>
</div>
</form>
<button type="submit" class="btn btn-success">Send</button>
Cancel
<br><br>
{% endblock %}
Here is the problem, and do not give action to form
crispy forms create the field not the button.
<form method="post">
{% csrf_token %}
<div class="row">
<div class="col-6">
{{ form.name|as_crispy_field }}
</div>
<div class="col-6">
{{ form.email|as_crispy_field }}
</div>
<div class="col-6">
{{ form.message|as_crispy_field }}
</div>
</div>
<button type="submit" class="btn btn-success">Send</button>
</form>
just add the button inside the form

How can I show error messages in change_password in 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.

Django modelformset_factory deleting objects marked by can_delete

Hello I have got question I have made modelformset_factory and in options I have choosen can_delete = True and now I don't know how to delete marked objects as 'DELETE' : True to delete them from database. I was trying to do this in some ways and it didnt work. I was looking for it also in django formsetmodels documentation but this didnt help me. With this option can_delete = True I get additional checkbox in my html page Delete and marking him only prints me in console on print:
{'username': 'sw', 'email': 'a#gmail.com', 'city': 'ss', 'code': 12345, 'id': , 'DELETE': False}
Saving forms to database is working but I dont know how to delete marked forms from database.
I would be very thankful for every help.
I have made modelformset_factory from model in models.py
class TestModel(models.Model):
username = models.CharField(max_length=120)
email = models.EmailField()
city = models.CharField(max_length=120)
code = models.IntegerField()
#W admin panelu za miast TestModel object bedzie username
def __str__(self):
return self.username
Then I have added in my views.py function:
def django_modelformset(request):
TestModelFormset = modelformset_factory(TestModel, fields=['username', 'email', "city",
"code"], extra=1, can_delete=True)
formset = TestModelFormset(request.POST or None)
if formset.is_valid():
for form in formset:
print(form)
print(form.cleaned_data)
form.save()
context = {"formset": formset}
return render(request, "modelformset.html", context)
My modelformset.html looks like this:
<form method="POST" action="">
{% csrf_token %}
{{ formset.management_form}}
{% for form in formset %}
<div>
{{ form.as_p }}
<hr/>
</div>
{% endfor %}
<input type="submit" value="Save">
I haven't personally had to do this, but from the docs it seems you have a few options.
Call save on the formset instead of each form.
if formset.is_valid():
formset.save()
If you must loop through each form you could something like this.
if formset.is_valid():
for form in formset:
print(form.cleaned_data)
if form.cleaned_data["DELETE"]:
# Do what you want with the form data
# i.e. get the object from the database and delete it.
else:
form.save()
Loop through the deleted forms separately.
if formset.is_valid():
forms = formset.save(commit=False)
for object in formset.deleted_objects:
object.delete()
It's work for me
view.py
Blog_MetaFormSet = modelformset_factory(Metas, form=MetaForm, extra=0, can_delete=True)
Blog_MetaQuerySet = Metas.objects.filter(blog=blog_obj).order_by('created_at')
contex={
"blog_meta_formset": Blog_MetaFormSet(request.POST,queryset=Blog_MetaQuerySet),
}
if blog_meta_formset.is_valid():
for metaform in blog_meta_formset:
meta_obj = metaform.save(commit=False)
meta_obj.blog = blog_obj
if metaform.cleaned_data["DELETE"]==True:
meta_obj.delete()
else:
meta_obj.save()
In Templates
<div class="row">
<div id="cfield-form-list"> {{ blog_meta_formset.management_form }} {% for meta_form in blog_meta_formset %}
<div id="form-{{forloop.counter0}}" class="cfield-form xrow">
<div class="col-md-12 mb-3">
<div class="row d-flex align-items-center">
<div class="col-md-4">
<label class="form-label">Name</label> {{ meta_form.title|attr:"class:form-control"|attr:"type:text" }} </div>
<div class="col-md-4">
<label class="form-label">Value</label> {{ meta_form.value|attr:"class:form-control"|attr:"rows:2" }} </div>
<div class="col-md-4">
<div class="form-check custom-checkbox mb-3 checkbox-primary"> {{ meta_form.DELETE|attr:"class:form-check-input"|attr:"type:checkbox" }}
<label class="form-check-label" for="customCheckBox2">Delete</label>
</div>
</div>
</div>
</div> {{meta_form.id}} </div> {% endfor %} </div>
<div id="empty_form" class="hidden">
<div class="col-md-12 mb-3">
<div class="row d-flex align-items-center">
<div class="col-md-4">
<label class="form-label">Name</label> {{ blog_meta_formset.empty_form.title|attr:"type:text"|attr:"class:form-control" }} </div>
<div class="col-md-4">
<label class="form-label">Value</label> {{ blog_meta_formset.empty_form.value|attr:"class:form-control"|attr:"rows:2" }} </div>
<div class="col-md-4">
<div class="form-check custom-checkbox mb-3 checkbox-primary"> {{ blog_meta_formset.empty_form.DELETE|attr:"class:form-check-input"|attr:"type:checkbox" }}
<label class="form-check-label" for="customCheckBox2">Delete</label>
</div>
</div>
<div class="col-md-4">
<button type="button" class="btn btn-danger remove_cfield" rel="">Delete</button>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<button type="button" id="add-cfield" class="btn btn-primary mb-3 mt-3 ">Add Custom Field</button>
</div>
</div>
In js
const totalNewForms = document.getElementById('id_form-TOTAL_FORMS')
const addMoreBtn = document.getElementById('add-cfield')
addMoreBtn.addEventListener('click',add_new_form)
function add_new_form(event){
if (event){
event.preventDefault()
}
const currentCF_Forms = document.getElementsByClassName('cfield-form')
console.log(currentCF_Forms)
const currentCF_FormCount = currentCF_Forms.length //+ 1
const formCopyTarget = document.getElementById('cfield-form-list')
const copyEmptyFormEl = document.getElementById('empty_form').cloneNode(true)
//remove class hidden
copyEmptyFormEl.setAttribute('class','cfield-form xrow')
copyEmptyFormEl.setAttribute('id',`form-${currentCF_FormCount}`)
const regex = new RegExp('__prefix__','g')
copyEmptyFormEl.innerHTML = copyEmptyFormEl.innerHTML.replace(regex,currentCF_FormCount)
totalNewForms.setAttribute('value', currentCF_FormCount +1)
//now add new empty form element to our html form
formCopyTarget.append(copyEmptyFormEl)

How can I deal with error message when not using {{form}} in Django template?

I implemented Login and it works good except error message.
If I used {{ form.as_p }}, it shows error message.
<form id="loginform" class="form-horizontal" role="form" method="post" action="{% url 'users:login' %}">
{% csrf_token %}
<!-- id / pw -->
{{ form.as_p }}
<div class="form-group">
<!-- Button -->
<div class="btn-controls">
<div class="row">
<input id="btn-login" class="btn btn-success" type="submit" name="login_submit" value="로 그 인" />
<input type="hidden" name="next" value={{ request.GET.next}} />
<a id="btn-fblogin" href="{% url 'social:begin' backend='facebook' %}" class="btn btn-primary col-xs-12"><i class="icon-facebook"></i> 1초만에 페이스북으로 로그인 </a>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12 control">
<div class="signup">
아직 차차다방 회원이 아니세요? &nbsp
가입하기
</div>
<div class="forget">
비밀번호를 잊어버리셨나요?
</div>
</div>
</div>
</form>
But when I change template like this, it doesn't show any error when I type wrong id or pw...
<form id="loginform" class="form-horizontal" role="form" method="post" action="{% url 'users:login' %}">
{% csrf_token %}
<div class="input-group">
<span class="input-group-addon"><i class="icon-user"></i></span>
<input id="id_username" type="text" class="form-control" name="username" value="" placeholder="username">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="icon-lock"></i></span>
<input id="id_password" type="password" class="form-control" name="password" placeholder="password">
</div>
<div class="form-group">
<!-- Button -->
<div class="btn-controls">
<div class="row">
<input id="btn-login" class="btn btn-success" type="submit" name="login_submit" value="로 그 인" />
<input type="hidden" name="next" value={{ request.GET.next}} />
<a id="btn-fblogin" href="{% url 'social:begin' backend='facebook' %}" class="btn btn-primary col-xs-12"><i class="icon-facebook"></i> 1초만에 페이스북으로 로그인 </a>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12 control">
<div class="signup">
아직 차차다방 회원이 아니세요? &nbsp
가입하기
</div>
<div class="forget">
비밀번호를 잊어버리셨나요?
</div>
</div>
</div>
</form>
How can I make it show error message even if I don't user {{ form.xx }} ?
Here is my LoginView.
from django.utils.http import is_safe_url
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters
from django.views.generic import FormView
from users.forms import MyUserCreationForm
class LoginView(FormView):
form_class = AuthenticationForm
redirect_field_name = REDIRECT_FIELD_NAME
# template_name is fake one.
# This view only process POST request from users/login_signup.html
template_name = "users/login_signup.html"
#method_decorator(sensitive_post_parameters('password'))
#method_decorator(csrf_protect)
#method_decorator(never_cache)
def dispatch(self, request, *args, **kwargs):
# Sets a test cookie to make sure the user has cookies enabled
request.session.set_test_cookie()
return super(LoginView, self).dispatch(request, *args, **kwargs)
def form_valid(self, form):
auth_login(self.request, form.get_user())
# If the test cookie worked, go ahead and
# delete it since its no longer needed
if self.request.session.test_cookie_worked():
self.request.session.delete_test_cookie()
return super(LoginView, self).form_valid(form)
def get_context_data(self, *args, **kwargs):
context = super(LoginView, self).get_context_data(*args, **kwargs)
return context
def get_success_url(self):
return self.request.POST.get("next")
I didn't get what exactly your question is, and also don't know if it is your answer or not, but i just say it!
You should use your django form that you passed from view in your template to be able to validate the form after the submission of form.
and if your concern is how to show the form properly in they way you want, it has another solution. you can represent the form in the way you want like something below:
{% for field in form %}
<div class="input-group">
{% if field.name=="username" %}
<span class="input-group-addon"><i class="icon-user"></i></span>
<input id="id_username" type="text" class="form-control" name="username" value="" placeholder="username">
{% endif %}
{% if field.name=="password" %}
<span class="input-group-addon"><i class="icon-lock"></i></span>
<input id="id_password" type="password" class="form-control" name="password" placeholder="password">
{% endif %}
{% for error in field.errors %}
{{ error }}
{% endfor %}
</div>
{% endfor %}
As you can see, you can access the error of fields via field.errors and check the name of field with field.name!