Django Password Reset Confirm error (custom user model); update - 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:
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']
...

Related

Django Password Reset Confirm error (custom user model)

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>

Why does form.is_valid return false. Please advice

I have a project where one books a room online then is directed to the checkout page where you input a phone which is required in the backend. Code is as below:
forms.py
from django import forms
class AvailabilityForm(forms.Form):
check_in = forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M'], required=True)
check_out = forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M'], required=True)
class PhoneNoForm(forms.Form):
phone_no = forms.IntegerField(required=True)
views.py
class RoomDetailView(View):
def get(self, request, *args, **kwargs):
category = self.kwargs.get('category', None)
got_category = get_room_category(category)
print(category)
print(got_category)
form = AvailabilityForm()
if got_category is not None:
context = {
'category':got_category,
'form':form
}
return render(request, 'detail.html', context)
else:
return HttpResponse("Category Nyet!")
def post(self, request, *args, **kwargs):
category = self.kwargs.get('category', None)
form = AvailabilityForm(request.POST)
if form.is_valid():
data = form.cleaned_data
available_rooms = get_available_rooms(category, data['check_in'], data['check_out'] )
if available_rooms is not None:
room = available_rooms[0]
context = {
'room':room
}
return render(request, 'booking/checkout.html', context)
else:
return HttpResponse("We're out of those rooms" )
else:
return HttpResponse('Form invlid')
class CheckoutView(TemplateView):
template_name = 'booking/checkout.html'
def get_phone(request):
if request.POST:
phone_no = request.POST.get('PhoneNo', None)
print(phone_no)
cl = MpesaClient()
# Use a Safaricom phone number that you have access to, for you to be able to view the prompt
phone_number = phone_no
amount = 1
account_reference = 'reference'
transaction_desc = 'Description'
callback_url = 'https://darajambili.herokuapp.com/express-payment'
# callback_url = request.build_absolute_uri(reverse('booking:mpesa_stk_push_callback'))
response = cl.stk_push(phone_number, amount, account_reference, transaction_desc, callback_url)
return HttpResponse(response.text)
else:
return HttpResponse('This is else')
checkout.html
<div>
<form action="" method="POST">
{% csrf_token %}
<label for="Input No.">Input Phone No. :</label>
<input type="number" name="id_PhoneNo" id="PhoneNo">
<input type="submit" value="Proceed">
</form>
</div>
detail.html
<form id="booking-form" action="" method="POST">
{% csrf_token %}
<div class="input-div">
<label for="id_check_in">Check In : </label>
<input type="datetime-local" id="id_check_in" name="check_in">
</div>
<div class="input-div">
<label for="id_check_out">Check Out : </label>
<input type="datetime-local" id="id_check_out" name="check_out">
</div>
<div class="input-div">
<button type="submit">Book the Room</button>
</div>
</form>
form.is_valid returns False. I have tried using GET method but i need the phone number for more processing hence my insistence on using POST. If possible, help me fast. Where is the problem? Sorry if it's too much code.
You need to return the errors to the HTML pages to see why the error is occurring. So, if the form is not valid, send that to HTML page by:
def post(self, request, *args, **kwargs):
category = self.kwargs.get('category', None)
form = AvailabilityForm(request.POST)
if form.is_valid():
...
else:
category = self.kwargs.get('category', None)
got_category = get_room_category(category)
context = {
'category':got_category,
'form':form
}
return render(request, 'detail.html', context)
And render the errors like this(as per documentation):
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
FYI, rather than directly subclassing the View, you should use FormView. Here is an example code on how to use:
class RoomDetailView(FormView):
form_class = AvailabilityForm
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
category = self.kwargs.get('category', None)
got_category = get_room_category(category)
if got_category is not None:
context.update({
'category':got_category,
})
return context
else:
raise Http404("Category does not exist")
def form_valid(self, form):
data = form.cleaned_data
available_rooms = get_available_rooms(category, data['check_in'], data['check_out'] )
if available_rooms is not None: # this part should be in a separate view
room = available_rooms[0]
context = {
'room':room
}
return render(request, 'booking/checkout.html', context)
else:
return HttpResponse("We're out of those rooms" )

Why doesn't {% if %} {% else %} construction work in Django template?

So I am trying to display "YOU" above the comment if it's in fact a comment that has been posted by current user, otherwise I am trying to display just a username of one who left a comment.
But somehow if/else doesn't work. Can anyone please tell me what am I doing wrong?
Thank you beforehand!
my models.py
class Comments(models.Model):
commented_by = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
comment = models.TextField(max_length=300)
def __str__(self):
return self.comment
my forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comments
fields = ['comment']
widgets = {'comment': forms.Textarea(attrs={'class': 'form-control', 'rows': 5})}
my views.py
class Comment(CreateView, LoginRequiredMixin):
form_class = CommentForm
template_name = 'app/comments.html'
login_url = 'login'
success_url = reverse_lazy('comments')
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.commented_by = self.request.user
self.object.save()
if self.object:
messages.success(self.request, 'Success')
else:
messages.error(self.request, 'Error')
return redirect(self.get_success_url())
def get_initial(self):
initial = super().get_initial()
initial['comment'] = 'Please leave your comment here'
return initial
def get_context_data(self, **kwargs):
context = super().get_context_data()
context['comments'] = Comments.objects.all()
return context
and my condition from the template:
<div>
<div class="commentsContainer">
{% for comment in comments %}
{% if comment.commented_by == user.username %}
<h4>YOU</h4>
{% else %}
{{comment.commented_by}}
{% endif %}
<div class="comment">
{{comment}}
</div>
{% endfor %}
</div>
comment.commented_by will give you an instance of the user model, whereas user.username will give you a string which is the user's username. Hence comment.commented_by == user.username will always give you False. Instead you should write:
{% if comment.commented_by == user %}
<h4>YOU</h4>
{% else %}
{{ comment.commented_by }}
{% endif %}

Django UpdateView Profile-Save-Data-No-Work

Holla ppl. Im new in django and trying my best , but at this point im stuck and need some help.
The thing is: i cant update my user-profile via template. when i do some changes --- in console i can see POST, then i get redirect by "success_url". no errors shown.but new data is not saved.
django 1.11.4
here my codes:
Models:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(blank=True)
location = models.CharField(max_length=30, blank=True)
bio = models.TextField(max_length=500, blank=True)
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
Views:
class RegisterView(CreateView):
template_name = "registration/register.html"
form_class = RegisterForm
success_url = '/'
def dispatch(self, *args, **kwargs):
# if self.request.user.is_authenticated():
# return redirect("/logout")
return super(RegisterView, self).dispatch(*args, **kwargs)
class ProfileUpdateView(UpdateView):
model = Profile
form_class = ProfileForm
template_name = 'profiles/profile-detail-update.html'
success_url = '/'
def get_object(self, **kwargs):
username = self.kwargs.get("username")
if username is None:
raise Http404
return get_object_or_404(User, username__iexact=username)
Forms
class RegisterForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username',)
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 don't match")
return password2
def save(self, commit=True):
user = super(RegisterForm, self).save(commit=True)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('avatar', 'location', 'bio', 'active',)
URL
url(r'^(?P<username>[\w-]+)/$', ProfileUpdateView.as_view(), name='update'),
Template:
{% extends 'base.html' %}
{% block content %}
<p>name: {{ user.username }}</p>
<p>location: {{ user.profile.location }}</p>
{% if user.profile.avatar %}
<img style="width: 200px" src="{{ user.profile.avatar.url }}"/>
{% endif %}
<hr/>
{% include 'snippets/form.html' %}
{% endblock %}
Included snippet:
<div class="form pt-2">
{% if form.errors.non_field_errors %}
{{ form.errors.non_field_errors }}
{% endif %}
<form method='POST' action='' enctype='multipart/form-data'> {% csrf_token %}
{{ form.as_p }}
<button class='btn btn-success' type='submit'>Save</button>
<button onclick="window.history.back();" class="btn btn-danger" type="button">Go back</button>
</form>
</div>
SOS.
In your ProfileUpdateView you are passing an User instance to the form, instead of a Profile instance:
class ProfileUpdateView(UpdateView):
# ...
def get_object(self, **kwargs):
username = self.kwargs.get("username")
if username is None:
raise Http404
return get_object_or_404(Profile, user__username__iexact=username)

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 %}