0

I'm trying to make form and method which allows users to change their password. When user type their password into two inputs than form will check if those are same and update db. However I got this error and I couldn't solve it.

error message

NoReverseMatch at /blog/password_change/blue/
Reverse for 'profile' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'blog/profile/(?P<username>[-\\w.]+)/$']

urls.py

url(r'^password_change/(?P<username>[-\w.]+)/$', views.password_change, name='password_change'),
url(r'^profile/(?P<username>[-\w.]+)/$', views.profile, name='profile'),

views.py

def password_change(request, username):
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(reverse('blog:profile'))
    else:
        return redirect(reverse('blog:profile'))
else:
    form = PasswordChangeForm(user=request.user)

    return HttpResponseRedirect('/blog/')

profile.html. this is the template.

 <form class="form-horizontal" role="form" action="{% url'blog:password_change' user.username %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<label for="password1">new password</label>
 <div class="row">
    <input type="password" name="password1" id="password1"/></div>
<div class="row">
<label for="password2">password check</label></div>
 <div class="row">
    <input type="password" name="password2" id="password2"/></div>
 <div class="row">  
      <button type="submit" class="button-primary">change password</button></div>

views.py

def password_change(request, username):
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(reverse('blog:profile'))
    else:
        return redirect(reverse('blog:profile'))
else:
    form = PasswordChangeForm(user=request.user)

    return HttpResponseRedirect('/blog/')

This is forms.py

 class PasswordChangeForm(forms.ModelForm):
    error_messages = {
    'password_mismatch': ("The two password fields didn't match."),
}
password1 = forms.CharField(
    label=("Password"),
    strip=False,
    widget=forms.PasswordInput,
    help_text=password_validation.password_validators_help_text_html(),
)
password2 = forms.CharField(
    label=("Password confirmation"),
    widget=forms.PasswordInput,
    strip=False,
    help_text=("Enter the same password as before, for verification."),
)

class Meta:
    model = User
    fields = ("username",)
    field_classes = {'username': UsernameField}

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    if self._meta.model.USERNAME_FIELD in self.fields:
        self.fields[self._meta.model.USERNAME_FIELD].widget.attrs.update({'autofocus': True})

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',
        )
    self.instance.username = self.cleaned_data.get('username')
    password_validation.validate_password(self.cleaned_data.get('password2'), self.instance)
    return password2

def save(self, commit=True):
    user = super().save(commit=False)
    user.set_password(self.cleaned_data["password1"])
    if commit:
        user.save()
    return user     
  • Please include the url for profile – Sayse Feb 16 '17 at 13:11
  • 1
    Possible duplicate of [What is a NoReverseMatch error, and how do I fix it?](http://stackoverflow.com/questions/38390177/what-is-a-noreversematch-error-and-how-do-i-fix-it) – Sayse Feb 16 '17 at 13:11

2 Answers2

2

As your error states, you need an argument for your username in profile url, which you don't provide at all.

For example:

 return redirect(reverse('blog:profile'))

should be

 return redirect(reverse('blog:profile', args=[form.user.get_username()]))
Alasdair
  • 298,606
  • 55
  • 578
  • 516
Sayse
  • 42,633
  • 14
  • 77
  • 146
  • 1
    Note you don't need `reverse` when using `redirect`. The final line can be simplified to `return redirect('blog:profile', form.user.get_username())` – Alasdair Feb 16 '17 at 13:45
0

You must pass username to reverse().

username = form.user.get_username()

reverse('blog:profile', kwargs={'username':username})

Luv33preet
  • 1,686
  • 7
  • 33
  • 66