Django Password Reset Confirm error (custom user model) - django

I am not that experienced writing Python/Back-end, but trying to improve. In development/localserver I am trying to create a password reset form... but I got the following error when accessing the link from the forgot password email - and before that the password was not saving:
get_context_data() missing 1 required positional argument: 'user'
forms.py (almost copy/paste from Django's form; minor changes)
class ResetPasswordForm(SetPasswordForm):
error_messages = {
'password_mismatch': static_textLanguage['page_user_passwordReset_alert_passwordNotMatch'],
'password_empty': static_textLanguage['global_alert_mandatoryField'],
'minimum_length': static_textLanguage['global_alert_minCharacters_password'],
}
new_password1 = forms.CharField(
required=False,
widget=forms.PasswordInput(attrs={
'id': 'page_userPasswordReset_content_form_input_passwordA',
'maxlength': '25',
'class': 'global_component_input_box'
}),
)
new_password2 = forms.CharField(
required = False,
widget=forms.PasswordInput(attrs={
'id': 'page_userPasswordReset_content_form_input_passwordB',
'maxlength': '25',
'class': 'global_component_input_box'
}),
)
def __init__(self, user, *args, **kwargs):
self.user = user
super(ResetPasswordForm, self).__init__(user, *args, **kwargs)
def clean_new_password1(self):
password1 = self.cleaned_data.get('new_password1')
if password1 == '' or password1 is None:
raise forms.ValidationError(self.error_messages['password_empty'], code='password_field_empty')
elif len(password1) < 8:
raise forms.ValidationError(self.error_messages['minimum_length'], code='password_too_short')
return password1
def clean_new_password2(self):
password1 = self.cleaned_data.get('new_password1')
password2 = self.cleaned_data.get('new_password2')
if password2 == '' or password2 is None:
raise forms.ValidationError(self.error_messages['password_empty'], code='password_field_empty')
if password1 and password2:
if password1 != password2:
raise ValidationError(self.error_messages['password_mismatch'], code='password_mismatch')
password_validation.validate_password(password2, self.user)
return password2
def save(self, commit=True):
password = self.cleaned_data["new_password1"]
self.user.set_password(password)
if commit:
self.user.save()
return self.user
views.py
class UserPasswordResetView(auth_views.PasswordResetConfirmView):
template_name = '../frontend/templates/frontend/templates.user/template.page_passwordReset.html'
form_class = ResetPasswordForm
post_reset_login = True
success_url = reverse_lazy('page_userLoginPrivate')
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.user
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.validlink:
context.update({
'validlink': True,
'form': self.form_class(),
'static_json_text': static_textLanguage,
'static_json_textGlobal': static_textGlobal
})
else:
context.update({
'validlink': False,
'form': None,
'title': _('Password reset unsuccessful'),
'static_json_text': static_textLanguage,
'static_json_textGlobal': static_textGlobal
})
return context
template.html (for purpose of this exercise .html was simplified)
<div class="wrapper_page_userPasswordReset">
{% if validlink %}
<form id="page_userPasswordReset_content_form" class="page_userPasswordReset_content_form" method="post" novalidate>
{% csrf_token %}
<div class="global_component_input_box_container">
{{ form.new_password1}}
</div>
<div id="page_userPasswordReset_input_passwordA_alert_errors" class="alert_message_input_danger_format">
{% if form.errors %}
{% for key, value in form.errors.items %}
{% if key == 'new_password1' %}
{{ value }}
{% endif %}
{% endfor %}
{% endif %}
</div>
<div class="global_component_input_box_container">
{{ form.new_password2}}
</div>
<div id="page_userPasswordReset_input_passwordB_alert_errors" class="alert_message_input_danger_format">
{% if form.errors %}
{% for key, value in form.errors.items %}
{% if key == 'new_password1' %}
{{ value }}
{% endif %}
{% endfor %}
{% endif %}
</div>
<button type="submit" id="page_userPasswordReset_content_form_button_submit" class="global_component_button button_background_green">{{ static_json_text.global_button_submit }}</button>
</form>
{% else %}
<button id="page_userPasswordReset_button_forgotPassword" class="global_component_button button_background_green">{{ static_json_text.page_user_passwordReset_notValidLink_button }}</button>
{% endif %}
</div>

Related

Django Password Reset Confirm error (custom user model); update

I am not that experienced writing Python/Back-end, but trying to improve. In development/localserver I am trying to create a password reset form... but I got the following error when accessing the link from the forgot password email - and before that the password was not saving:
init() missing 1 required positional argument: 'user'
forms.py (almost copy/paste from Django's form; minor changes)
class ResetPasswordForm(SetPasswordForm):
error_messages = {
'password_mismatch': static_textLanguage['page_user_passwordReset_alert_passwordNotMatch'],
'password_empty': static_textLanguage['global_alert_mandatoryField'],
'minimum_length': static_textLanguage['global_alert_minCharacters_password'],
}
new_password1 = forms.CharField(
required=False,
widget=forms.PasswordInput(attrs={
'id': 'page_userPasswordReset_content_form_input_passwordA',
'maxlength': '25',
'class': 'global_component_input_box'
}),
)
new_password2 = forms.CharField(
required = False,
widget=forms.PasswordInput(attrs={
'id': 'page_userPasswordReset_content_form_input_passwordB',
'maxlength': '25',
'class': 'global_component_input_box'
}),
)
def __init__(self, user, *args, **kwargs):
self.user = user
super(ResetPasswordForm, self).__init__(user, *args, **kwargs)
def clean_new_password1(self):
password1 = self.cleaned_data.get('new_password1')
if password1 == '' or password1 is None:
raise forms.ValidationError(self.error_messages['password_empty'], code='password_field_empty')
elif len(password1) < 8:
raise forms.ValidationError(self.error_messages['minimum_length'], code='password_too_short')
return password1
def clean_new_password2(self):
password1 = self.cleaned_data.get('new_password1')
password2 = self.cleaned_data.get('new_password2')
if password2 == '' or password2 is None:
raise forms.ValidationError(self.error_messages['password_empty'], code='password_field_empty')
if password1 and password2:
if password1 != password2:
raise ValidationError(self.error_messages['password_mismatch'], code='password_mismatch')
password_validation.validate_password(password2, self.user)
return password2
def save(self, commit=True):
password = self.cleaned_data["new_password1"]
self.user.set_password(password)
if commit:
self.user.save()
return self.user
views.py
class UserPasswordResetView(auth_views.PasswordResetConfirmView):
template_name = '../frontend/templates/frontend/templates.user/template.page_passwordReset.html'
form_class = ResetPasswordForm
post_reset_login = True
success_url = reverse_lazy('page_userLoginPrivate')
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.user
return kwargs
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
if self.validlink:
context.update({
'validlink': True,
'form': self.form_class(),
'static_json_text': static_textLanguage,
'static_json_textGlobal': static_textGlobal
})
else:
context.update({
'validlink': False,
'form': None,
'static_json_text': static_textLanguage,
'static_json_textGlobal': static_textGlobal
})
return context
template.html (for purpose of this exercise .html was simplified)
<div class="wrapper_page_userPasswordReset">
{% if validlink %}
<form id="page_userPasswordReset_content_form" class="page_userPasswordReset_content_form" method="post" novalidate>
{% csrf_token %}
<div class="global_component_input_box_container">
{{ form.new_password1}}
</div>
<div id="page_userPasswordReset_input_passwordA_alert_errors" class="alert_message_input_danger_format">
{% if form.errors %}
{% for key, value in form.errors.items %}
{% if key == 'new_password1' %}
{{ value }}
{% endif %}
{% endfor %}
{% endif %}
</div>
<div class="global_component_input_box_container">
{{ form.new_password2}}
</div>
<div id="page_userPasswordReset_input_passwordB_alert_errors" class="alert_message_input_danger_format">
{% if form.errors %}
{% for key, value in form.errors.items %}
{% if key == 'new_password1' %}
{{ value }}
{% endif %}
{% endfor %}
{% endif %}
</div>
<button type="submit" id="page_userPasswordReset_content_form_button_submit" class="global_component_button button_background_green">{{ static_json_text.global_button_submit }}</button>
</form>
{% else %}
<button id="page_userPasswordReset_button_forgotPassword" class="global_component_button button_background_green">{{ static_json_text.page_user_passwordReset_notValidLink_button }}</button>
{% endif %}
</div>
django
The error most likely happens because you defined user as positional argument (def __init__(self, user, *args, **kwargs):), but you pass the variable as a keyword argument (kwargs['user'] = self.user).
Instead of your code:
class ResetPasswordForm(SetPasswordForm):
...
def __init__(self, user, *args, **kwargs):
self.user = user
...
try changing it to this (so that the ResetPasswordForm looks for the user inside kwargs):
class ResetPasswordForm(SetPasswordForm):
...
def __init__(self, *args, **kwargs):
self.user = kwargs['user']
...

raise ValidationError doesn't work. Dgango

Anyone who can explain me, why my ValidationError in my form doesn't work? I can see "TEXT" in my terminal, but the ValidationError doesn't show.
Forms.py
def clean(self):
cleaned_data = super(CheckInForm, self).clean()
new_room = cleaned_data.get('room')
new_name = cleaned_data.get('name')
if Student.objects.filter(room=new_room).count() > 3:
if not Student.objects.filter(room=new_room, name__icontains=new_name):
print('TEXT')
raise ValidationError('The room is full')
It’s also worth noting that a similar def clean_room(self): function works fine in my code.
In this function, raise ValidationError works correctly.
def clean_room(self):
new_room = self.cleaned_data['room']
if new_room == '':
raise ValidationError('This field cannot be empty')
return new_room
Full length code:
class CheckInForm(forms.ModelForm):
class Meta:
model = Student
fields = ['room', 'name', 'faculty', 'place_status', 'form_studies',
'group', 'sex', 'mobile_number', 'fluorography', 'pediculosis',
'contract_number', 'agreement_date', 'registration', 'citizenship',
'date_of_birthday', 'place_of_birthday', 'document_number', 'authority',
'date_of_issue', 'notation'
]
widgets = {'room': forms.TextInput(attrs={'class': 'form-control'}),
'name': forms.TextInput(attrs={'class': 'form-control'}),
'faculty': forms.TextInput(attrs={'class': 'form-control'}),
}
def clean(self):
cleaned_data = super(CheckInForm, self).clean()
new_room = cleaned_data.get('room')
new_name = cleaned_data.get('name')
if Student.objects.filter(room=new_room).count() > 3:
if not Student.objects.filter(room=new_room, name__icontains=new_name):
print('TEXT')
raise ValidationError('The room is full')
def clean_room(self):
new_room = self.cleaned_data['room']
if new_room == '':
raise ValidationError('This field cannot be empty!')
return new_room
{% extends 'hostel/base_home.html' %}
{% block check_in %}
<form action="{% url 'check_in_update_url' id=student.id %}" method="post">
{% csrf_token %}
{% for field in bound_form %}
<div class="from-group">
{{ field.label }}
{{ field }}
{% for error in form.non_field_errors %}
{{error}}
{% endfor %}
{% if field.errors %}
<div class="alert alert-danger">
{{ field.errors }}
</div>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Update</button>
</form>
{% endblock %}

Custom registration form. Confirm password

I used custom form for register users. I want do validation for confirm password.
forms.py:
class RegistrationForm(UserCreationForm):
'''Register for new users'''
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class Meta:
model = get_user_model()
fields = {'username', 'password1', 'password2', 'email', 'first_name', 'last_name'}
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
if commit:
user.save()
return user
template:
<div class="input-group register">
{{ form.password.errors }}
<label for="id_password1">Password: </label>
{{ form.password1 }}
</div>
<div class="input-group register">
{{ form.password.errors }}
<label for="id_password2">Confirm password: </label>
{{ form.password2 }}
</div>
views.py
def registration_view(request):
context = {}
context.update(csrf(request))
context['form'] = RegistrationForm()
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
newuser = auth.authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password2']
)
auth.login(request, newuser)
return redirect('home')
else:
context['form'] = form
return render(request, '/registration.html', context)
How can I add validation for password(also confirm password)?
You inherit from UserCreationForm [GitHub]. This form already does that for you.
Indeed: the clean_password2 will validate that the two passwords are the same:
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
The _post_clean function will validate that the password is a valid password:
def _post_clean(self):
super()._post_clean()
# Validate the password after self.instance is updated with form data
# by super().
password = self.cleaned_data.get('password2')
if password:
try:
password_validation.validate_password(password, self.instance)
except forms.ValidationError as error:
self.add_error('password2', error)
Finally in the save() it will use .set_password() to set the password. This is necessary, since Django's User model will, like any good user model, hash the password.
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
You thus should not interfere with these. You here only want to add first_name and last_name. So you can add that logic with:
class RegistrationForm(UserCreationForm):
'''Register for new users'''
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class Meta:
model = get_user_model()
fields = ['username', 'email', 'first_name', 'last_name']
That's all, since the ModelForm will take care of that.
Note that authenticate in your view is probably not necessary, since if you construct a user, it should authenticate. You can just login here:
def registration_view(request):
context = {}
context.update(csrf(request))
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
newuser = form.save()
auth.login(request, newuser)
return redirect('home')
else:
form = RegistrationForm()
context['form'] = form
return render(request, '/registration.html', context)
Try to use this in your register template
<form method="post" id="register-account-form">
{% csrf_token %}
{% for field in form %}
{% if field.help_text %}
<div class="notification error closeable">
<small style="color: grey">{{ field.help_text }}</small>
<a class="close" href="#"></a>
</div>
{% endif %}
{% for error in field.errors %}
<div class="notification error closeable">
<p style="color: red">{{ error }}</p>
<a class="close" href="#"></a>
</div>
{% endfor %}
{% endfor %}
<div class="input-with-icon-left">
<i class="icon-feather-user"></i>
{{ form.username }}
</div>
I find mistake
<div class="input-group register">
{{ form.password1.errors }}
<label for="id_password1">Пароль: </label>
{{ form.password1 }}
</div>
<div class="input-group register">
{{ form.password2.errors }}
<label for="id_password2">Подтвердите пароль: </label>
{{ form.password2 }}
</div>

django how to authenticate user until verify email

How to authenticate user until he verify the email?
In my sign up process, I create the User, which means he can login even without verify email. Is there a build-in method to set a un-verified status on a User?
models.py
email_active = models.BooleanField(default=False,
verbose_name=u'Email active ')
views.py
username = request.POST.get("username")
password = request.POST.get("password")
user = authenticate(username=username, password=password)
if user is not None:
if user.email_active:
login(self.request, user)
return HttpResponse("login success")
else:
return HttpResponse("user email is not active")
else:
return HttpResponse("username or password error")
you can active email by send email with verify_code,user can use verify_code to active their email.
Demo:
models.py:
class EmailVerify(models.Model):
owner = models.ForeignKey(User,
on_delete=models.CASCADE,
verbose_name='owner')
verify_code = models.CharField(max_length=254,
null=True,
verbose_name='verify_code ')
def update(self):
self.verify_code = self.generate_key()
self.save()
return self.verify_code
def get_active_email_url(self, request):
from django.urls import reverse
url = '{}?active_code={}'.format(request.build_absolute_uri(reverse('user_login', args=())), self.verify_code)
return url
#staticmethod
def generate_key():
return binascii.hexlify(os.urandom(20)).decode()
class Meta:
verbose_name = 'EmailVerify'
utils.py :
def send_active_email(request, user):
current_site = get_current_site(request)
site_name = current_site.name
if EmailVerify.objects.filter(owner=user, category=0).exists():
verify = EmailVerify.objects.filter(owner=user).first()
else:
verify = EmailVerify.objects.create(owner=user)
verify.update()
title = u"{} active email".format(site_name)
message = "".join([
u"click this link can active your email:\n\n",
"{}\n\n".format(verify.get_active_email_url(request=request)),
])
try:
send_mail(title, message, settings.DEFAULT_FROM_EMAIL, [user.email])
message = "success"
except ConnectionRefusedError as e:
message = e.strerror
except Exception as e:
message = str(e)
return message
views.py
class LoginView(BaseContextMixin, FormView):
template_name = 'user/login.html'
form_class = LoginForm
success_url = reverse_lazy('index')
def get_context_data(self, **kwargs):
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
if 'active_email' in self.request.GET:
active_email = self.request.GET.get('active_email')
try:
user = User.objects.get(email=active_email, email_active=False)
kwargs['message'] = send_active_email(self.request, user)
except (ObjectDoesNotExist, MultipleObjectsReturned):
kwargs['message'] = 'email not exist or actived'
if 'active_code' in self.request.GET:
active_code = self.request.GET.get('active_code')
try:
email_verify = EmailVerify.objects.get(verify_code=active_code)
email_verify.owner.email_active = True
email_verify.owner.save()
email_verify.delete()
kwargs['message'] = 'email {} actived'.format(email_verify.owner.email)
except ObjectDoesNotExist:
kwargs['message'] = 'unless link'
except MultipleObjectsReturned:
EmailVerify.objects.filter(verify_code=active_code).delete()
kwargs['message'] = 'error!'
return super(LoginView, self).get_context_data(**kwargs)
def get_form(self, form_class=None):
if form_class is None:
form_class = self.get_form_class()
return form_class(request=self.request, **self.get_form_kwargs())
forms.py:
class LoginForm(forms.Form):
active_email = None
username = forms.CharField(label='username')
password = forms.CharField(widget=forms.PasswordInput, label='password')
def __init__(self, request, *args, **kwargs):
super(LoginForm, self).__init__(*args, **kwargs)
self.request = request
self.fields['username'].widget.attrs.update({'class': 'form-control',
"placeholder": self.fields['username'].label})
self.fields['password'].widget.attrs.update({'class': 'form-control',
"placeholder": self.fields['password'].label})
def clean(self):
username = self.cleaned_data["username"]
password = self.cleaned_data["password"]
user = authenticate(username=username, password=password)
if user is not None:
if user.email_active:
login(self.request, user)
else:
self.active_email = user.email
self.add_error("username", "not active")
else:
self.add_error("username", "username or password error")
login.html:
{% extends "user/user_base.html" %}
{% block content %}
<div class="login-box">
<div class="login-logo">
{{ website_title|default_if_none:'' }}
</div>
<div class="login-box-body">
<form method="post" action="{% url 'user_login' %}" class="form">
{% csrf_token %}
{% for field in form %}
<div class="form-group no-margin {% if field.errors %} has-error {% endif %}">
<label class="control-label" for="{{ field.id_for_label }}">
<b>{{ field.label }}</b>
{% if message %}
{% ifequal field.name 'username' %}{{ message }}{% endifequal %}
{% endif %}
{% if field.errors %}
{{ field.errors.as_text }}
{% ifequal field.errors.as_text '* not active' %}
<a href="{% url 'user_login' %}?active_email={{ form.active_email }}">
send active emial
</a>
{% endifequal %}
{% endif %}
</label>
{{ field }}
</div>
{% endfor %}
<div class="row">
<div class="col-md-6">
<button id="btn_login" type="submit" style="width: 100%"
class="btn btn-raised btn-primary">Login
</button>
</div>
</div>
</form>
</div>
</div>
{% endblock %}

Django FormWizard with different templates

I am trying to use FormWizard to make a registration for new users. Because in some steps I would need to use js,formsets, and photos, I decided to make a different template for each step. But then I got an error :
ValidationError at /registration_steps
[u'\u0414\u0430\u043d\u043d\u044b\u0435 ManagementForm \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0438\u043b\u0438 \u0431\u044b\u043b\u0438 \u0438\u0441\u043a\u0430\u0436\u0435\u043d\u044b.']
forms.py
class ApplicantForm1(forms.ModelForm):
password1 = forms.CharField(
label='Password',
widget=forms.PasswordInput
)
password2 = forms.CharField(
label='confirm',
widget=forms.PasswordInput
)
travel_passport = forms.ChoiceField(
choices=((False, 'Нет'), (True, 'Да')),
widget=forms.Select
)
def clean_password2(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2 and password1 != password2:
raise forms.ValidationError('Passwords dont match')
return password2
def save(self, commit=True):
user = super(ApplCreaForm, self).save(commit=False)
user.set_password(self.cleaned_data['password1'])
user.isempl=0
if commit:
user.save()
return user
class Meta:
model = ExtUser
fields = ['email','firstname', 'lastname', 'middlename', 'date_of_birth', 'gender', 'family_position',
'driver_license', 'driver_license_category',]
class ApplicantForm2(forms.ModelForm):
class Meta:
model = ExtUser
fields = ['country','region','city', 'nearcity', 'travel_passport', 'travel_passport_end_date','metro', 'mobile_sms', 'mobile_double', 'email_double',
'web', 'vkontakte', 'facebook','odnoklasniki','skype','whatsapp','viber','ready_to_move','ready_to_move_where',]
views.py
FORMS_REG = [("reg_step1", ApplicantForm1),
("reg_step2", ApplicantForm2),
# ("ApplicantForm3", ApplicantForm3),
# ("ApplicantForm4", ApplicantForm4),
# ("ApplicantForm5", ApplicantForm5),
# ("ApplicantForm6", ApplicantForm6),
# ("ApplicantForm7", ApplicantForm7),
]
TEMPLATES_REG = {"reg_step1": "registration_steps/reg_step1.html",
"reg_step2": "registration_steps/reg_step2.html",
#"reg_step3": "registration_steps/reg_step3.html",
#"reg_step4": "registration_steps/reg_step4.html",
#"reg_step5": "registration_steps/reg_step5.html",
#"reg_step6": "registration_steps/reg_step6.html",
#"reg_step7": "registration_steps/reg_step7.html",
}
class ApplicantWizard(SessionWizardView):
instance = None
def get_template_names(self):
return [TEMPLATES_REG[self.steps.current]]
def get_form_instance( self, step ):
if self.instance is None:
self.instance = ExtUser()
return self.instance
def done(self, form_list, **kwargs):
self.instance.save()
return render_to_response('app/successpage.html', {
'title':"Registration complited" ,
})
urls.py
url(r'^registration_steps$', ApplicantWizard.as_view(FORMS_REG)),
templates reg_step1.html and reg_step2.html (for now they are same)
{% extends "layout/layout_main.html" %}
{% block content %}
<p> Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
{% for field in form %}
{{field.error}}
{% endfor %}
<form action="" method="post">{% csrf_token %}
<table>
{{wizard.managment_form}}
{{ wizard.form }}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">"first step"</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"prev step"</button>
{% endif %}
<input type="submit" value="Submit" />
</form>
{% endblock %}
As form wizard complains about the missing management form, the problem seems to be related to nested formsets. Make your relevant template section look like:
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>