How do I extend the Django “login” form?












12















So, right now I'm doing the basic login. In urls.py, I go to django contrib login:



(r'^login/?$','django.contrib.auth.views.login',{'template_name':'login.html'}),


That shoots it to here:



@csrf_protect
@never_cache
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm):


That view uses the AuthenticationForm forms model:



class AuthenticationForm(forms.Form):
"""
Base class for authenticating users. Extend this to get a form that accepts
username/password logins.
"""
username = forms.CharField(label=_("Username"), max_length=30)
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)


So...my objective is to to change the username form! By adding this to it: widget = forms.TextInput(attrs={'placeholder': 'username'}). That's it. That's all I want to add to the username input box. But, I don't want to change the actual django forms.py file, since that's part of django contrib and I feel bad changing that file.



What do I do? Should I create a form that extends AuthenticationForm? If so, how do I import that? And how do I pass that in as an argument via my urls.py? I don't know what to do.










share|improve this question



























    12















    So, right now I'm doing the basic login. In urls.py, I go to django contrib login:



    (r'^login/?$','django.contrib.auth.views.login',{'template_name':'login.html'}),


    That shoots it to here:



    @csrf_protect
    @never_cache
    def login(request, template_name='registration/login.html',
    redirect_field_name=REDIRECT_FIELD_NAME,
    authentication_form=AuthenticationForm):


    That view uses the AuthenticationForm forms model:



    class AuthenticationForm(forms.Form):
    """
    Base class for authenticating users. Extend this to get a form that accepts
    username/password logins.
    """
    username = forms.CharField(label=_("Username"), max_length=30)
    password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)


    So...my objective is to to change the username form! By adding this to it: widget = forms.TextInput(attrs={'placeholder': 'username'}). That's it. That's all I want to add to the username input box. But, I don't want to change the actual django forms.py file, since that's part of django contrib and I feel bad changing that file.



    What do I do? Should I create a form that extends AuthenticationForm? If so, how do I import that? And how do I pass that in as an argument via my urls.py? I don't know what to do.










    share|improve this question

























      12












      12








      12


      7






      So, right now I'm doing the basic login. In urls.py, I go to django contrib login:



      (r'^login/?$','django.contrib.auth.views.login',{'template_name':'login.html'}),


      That shoots it to here:



      @csrf_protect
      @never_cache
      def login(request, template_name='registration/login.html',
      redirect_field_name=REDIRECT_FIELD_NAME,
      authentication_form=AuthenticationForm):


      That view uses the AuthenticationForm forms model:



      class AuthenticationForm(forms.Form):
      """
      Base class for authenticating users. Extend this to get a form that accepts
      username/password logins.
      """
      username = forms.CharField(label=_("Username"), max_length=30)
      password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)


      So...my objective is to to change the username form! By adding this to it: widget = forms.TextInput(attrs={'placeholder': 'username'}). That's it. That's all I want to add to the username input box. But, I don't want to change the actual django forms.py file, since that's part of django contrib and I feel bad changing that file.



      What do I do? Should I create a form that extends AuthenticationForm? If so, how do I import that? And how do I pass that in as an argument via my urls.py? I don't know what to do.










      share|improve this question














      So, right now I'm doing the basic login. In urls.py, I go to django contrib login:



      (r'^login/?$','django.contrib.auth.views.login',{'template_name':'login.html'}),


      That shoots it to here:



      @csrf_protect
      @never_cache
      def login(request, template_name='registration/login.html',
      redirect_field_name=REDIRECT_FIELD_NAME,
      authentication_form=AuthenticationForm):


      That view uses the AuthenticationForm forms model:



      class AuthenticationForm(forms.Form):
      """
      Base class for authenticating users. Extend this to get a form that accepts
      username/password logins.
      """
      username = forms.CharField(label=_("Username"), max_length=30)
      password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)


      So...my objective is to to change the username form! By adding this to it: widget = forms.TextInput(attrs={'placeholder': 'username'}). That's it. That's all I want to add to the username input box. But, I don't want to change the actual django forms.py file, since that's part of django contrib and I feel bad changing that file.



      What do I do? Should I create a form that extends AuthenticationForm? If so, how do I import that? And how do I pass that in as an argument via my urls.py? I don't know what to do.







      python django oop class authentication






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 10 '11 at 5:15









      TIMEXTIMEX

      69.8k275650959




      69.8k275650959
























          3 Answers
          3






          active

          oldest

          votes


















          22














          You need to subclass the AuthenticationForm class, and then you need to change your urls.py,



          class MyAuthenticationForm(AuthenticationForm):
          # add your form widget here
          widget = .....


          Then import this class into your urls.py file and update the call,



          (r'^login/?$','django.contrib.auth.views.login',{'template_name':'login.html', 'authentication_form':MyAuthenticationForm}),


          I'm too tired to lookup the links on the documentation site to see what type of field you need to use but this should do the trick to get you started without having to modify the django forms.py which you definitely should feel bad about changing!






          share|improve this answer































            1














            As milkypostman said, you need to make a subclass of auth.forms.AuthenticationForm.



            Then, you can use django-crispy-forms for put the placeholders into the fields you want. It's as simple as this:



            (app/forms.py)



            class LoginWithPlaceholder(AuthenticationForm):

            def __init__(self, *args, **kwargs):
            super(LoginWithPlaceholder, self).__init__(*args, **kwargs)
            self.helper = FormHelper()
            self.helper.form_show_labels = False
            self.helper.layout = Layout(Div(Field('username', placeholder='username'), css_class="form-group"),
            Div(Field('password', placeholder='password'), css_class="form-group"),
            Div(Submit('submit', 'Log in')))


            Finally, don't forget to use the crispy tag in your template:



            <div class="col-sm-6 col-sm-offset-3">        
            {% crispy form %}
            </div>





            share|improve this answer


























            • Thanks for the pointer to crispy!

              – rikb
              Mar 14 '17 at 17:56



















            0














            Here's another solution using path instead of the deprecated url, to create a custom version of the page and form to reset your password after following a link sent out in an email. I'm using Django 2 and Python 3.



            In my api app folder, I've created a folder templates/account with three files inside.



            base.html:



            <!DOCTYPE html>
            <html>
            <head>
            <title>{% block head_title %}{% endblock %}</title>
            {% block extra_head %}
            {% endblock %}
            </head>
            <body>
            {% block body %}
            {% block content %}
            {% endblock %}
            {% endblock %}
            {% block extra_body %}
            {% endblock %}
            </body>
            </html>


            password_reset_complete.html:



            {% extends "account/base.html" %}

            {% block content %}

            <h3>Password reset successful</h3>

            <p>Your password has been changed. Please log in using the link below.</p>

            <p><a href="/login/">Login</a></p>

            {% endblock %}


            password_reset_confirm.html:



            {% extends 'account/base.html' %}

            {% block content %}
            {% if validlink %}
            <h3>Enter your new password</h3>
            <form method="post">
            {% csrf_token %}
            {{ form.as_p }}
            <button type="submit">Change password</button>
            </form>
            {% else %}
            <p>
            The password reset link was invalid, possibly because it has already been used.
            Please request a new password reset.
            </p>
            {% endif %}
            {% endblock %}


            In my api app folder, I've created a file forms.py for my custom form which extends the default SetPasswordForm form.



            forms.py:



            from django import forms
            from django.contrib.auth.forms import SetPasswordForm
            from django.utils.translation import gettext, gettext_lazy as _
            from django.contrib.auth import password_validation

            class SetPasswordFormCustom(SetPasswordForm):
            new_password1 = forms.CharField(
            label=_("New password custom"),
            widget=forms.PasswordInput,
            strip=False,
            )
            new_password2 = forms.CharField(
            label=_("New password confirmation custom"),
            strip=False,
            widget=forms.PasswordInput,
            help_text=password_validation.password_validators_help_text_html(),
            )


            And finally urls.py:



            # api/urls.py
            from django.urls import include, path
            from django.contrib.auth import views
            from django.conf.urls import include, url
            from django.views.generic.base import RedirectView
            from .forms import SetPasswordFormCustom

            urlpatterns = [
            ...
            path('reset/<uidb64>/<token>/',
            views.PasswordResetConfirmView.as_view(template_name='account/password_reset_confirm.html',
            form_class=SetPasswordFormCustom),
            name='password_reset_confirm'),
            path('reset/done/', views.PasswordResetCompleteView.as_view(template_name='account/password_reset_complete.html'), name='password_reset_complete'),

            ]


            Note 'from .forms import SetPasswordFormCustom'. The . allows a file in the same folder to be imported.



            My reason for doing all this is that I haven't got reset password to work in my native React frontend, so I'm having to use the Django templates for this function. I want to be able to restyle it and have links that fit with my app as nearly as possible. But this method should generally allow you to create your own custom version of a Django auth form.






            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f4643884%2fhow-do-i-extend-the-django-login-form%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              22














              You need to subclass the AuthenticationForm class, and then you need to change your urls.py,



              class MyAuthenticationForm(AuthenticationForm):
              # add your form widget here
              widget = .....


              Then import this class into your urls.py file and update the call,



              (r'^login/?$','django.contrib.auth.views.login',{'template_name':'login.html', 'authentication_form':MyAuthenticationForm}),


              I'm too tired to lookup the links on the documentation site to see what type of field you need to use but this should do the trick to get you started without having to modify the django forms.py which you definitely should feel bad about changing!






              share|improve this answer




























                22














                You need to subclass the AuthenticationForm class, and then you need to change your urls.py,



                class MyAuthenticationForm(AuthenticationForm):
                # add your form widget here
                widget = .....


                Then import this class into your urls.py file and update the call,



                (r'^login/?$','django.contrib.auth.views.login',{'template_name':'login.html', 'authentication_form':MyAuthenticationForm}),


                I'm too tired to lookup the links on the documentation site to see what type of field you need to use but this should do the trick to get you started without having to modify the django forms.py which you definitely should feel bad about changing!






                share|improve this answer


























                  22












                  22








                  22







                  You need to subclass the AuthenticationForm class, and then you need to change your urls.py,



                  class MyAuthenticationForm(AuthenticationForm):
                  # add your form widget here
                  widget = .....


                  Then import this class into your urls.py file and update the call,



                  (r'^login/?$','django.contrib.auth.views.login',{'template_name':'login.html', 'authentication_form':MyAuthenticationForm}),


                  I'm too tired to lookup the links on the documentation site to see what type of field you need to use but this should do the trick to get you started without having to modify the django forms.py which you definitely should feel bad about changing!






                  share|improve this answer













                  You need to subclass the AuthenticationForm class, and then you need to change your urls.py,



                  class MyAuthenticationForm(AuthenticationForm):
                  # add your form widget here
                  widget = .....


                  Then import this class into your urls.py file and update the call,



                  (r'^login/?$','django.contrib.auth.views.login',{'template_name':'login.html', 'authentication_form':MyAuthenticationForm}),


                  I'm too tired to lookup the links on the documentation site to see what type of field you need to use but this should do the trick to get you started without having to modify the django forms.py which you definitely should feel bad about changing!







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 10 '11 at 5:37









                  milkypostmanmilkypostman

                  2,5151821




                  2,5151821

























                      1














                      As milkypostman said, you need to make a subclass of auth.forms.AuthenticationForm.



                      Then, you can use django-crispy-forms for put the placeholders into the fields you want. It's as simple as this:



                      (app/forms.py)



                      class LoginWithPlaceholder(AuthenticationForm):

                      def __init__(self, *args, **kwargs):
                      super(LoginWithPlaceholder, self).__init__(*args, **kwargs)
                      self.helper = FormHelper()
                      self.helper.form_show_labels = False
                      self.helper.layout = Layout(Div(Field('username', placeholder='username'), css_class="form-group"),
                      Div(Field('password', placeholder='password'), css_class="form-group"),
                      Div(Submit('submit', 'Log in')))


                      Finally, don't forget to use the crispy tag in your template:



                      <div class="col-sm-6 col-sm-offset-3">        
                      {% crispy form %}
                      </div>





                      share|improve this answer


























                      • Thanks for the pointer to crispy!

                        – rikb
                        Mar 14 '17 at 17:56
















                      1














                      As milkypostman said, you need to make a subclass of auth.forms.AuthenticationForm.



                      Then, you can use django-crispy-forms for put the placeholders into the fields you want. It's as simple as this:



                      (app/forms.py)



                      class LoginWithPlaceholder(AuthenticationForm):

                      def __init__(self, *args, **kwargs):
                      super(LoginWithPlaceholder, self).__init__(*args, **kwargs)
                      self.helper = FormHelper()
                      self.helper.form_show_labels = False
                      self.helper.layout = Layout(Div(Field('username', placeholder='username'), css_class="form-group"),
                      Div(Field('password', placeholder='password'), css_class="form-group"),
                      Div(Submit('submit', 'Log in')))


                      Finally, don't forget to use the crispy tag in your template:



                      <div class="col-sm-6 col-sm-offset-3">        
                      {% crispy form %}
                      </div>





                      share|improve this answer


























                      • Thanks for the pointer to crispy!

                        – rikb
                        Mar 14 '17 at 17:56














                      1












                      1








                      1







                      As milkypostman said, you need to make a subclass of auth.forms.AuthenticationForm.



                      Then, you can use django-crispy-forms for put the placeholders into the fields you want. It's as simple as this:



                      (app/forms.py)



                      class LoginWithPlaceholder(AuthenticationForm):

                      def __init__(self, *args, **kwargs):
                      super(LoginWithPlaceholder, self).__init__(*args, **kwargs)
                      self.helper = FormHelper()
                      self.helper.form_show_labels = False
                      self.helper.layout = Layout(Div(Field('username', placeholder='username'), css_class="form-group"),
                      Div(Field('password', placeholder='password'), css_class="form-group"),
                      Div(Submit('submit', 'Log in')))


                      Finally, don't forget to use the crispy tag in your template:



                      <div class="col-sm-6 col-sm-offset-3">        
                      {% crispy form %}
                      </div>





                      share|improve this answer















                      As milkypostman said, you need to make a subclass of auth.forms.AuthenticationForm.



                      Then, you can use django-crispy-forms for put the placeholders into the fields you want. It's as simple as this:



                      (app/forms.py)



                      class LoginWithPlaceholder(AuthenticationForm):

                      def __init__(self, *args, **kwargs):
                      super(LoginWithPlaceholder, self).__init__(*args, **kwargs)
                      self.helper = FormHelper()
                      self.helper.form_show_labels = False
                      self.helper.layout = Layout(Div(Field('username', placeholder='username'), css_class="form-group"),
                      Div(Field('password', placeholder='password'), css_class="form-group"),
                      Div(Submit('submit', 'Log in')))


                      Finally, don't forget to use the crispy tag in your template:



                      <div class="col-sm-6 col-sm-offset-3">        
                      {% crispy form %}
                      </div>






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited May 23 '17 at 12:09









                      Community

                      11




                      11










                      answered Feb 1 '17 at 3:13









                      rvliscanorvliscano

                      885




                      885













                      • Thanks for the pointer to crispy!

                        – rikb
                        Mar 14 '17 at 17:56



















                      • Thanks for the pointer to crispy!

                        – rikb
                        Mar 14 '17 at 17:56

















                      Thanks for the pointer to crispy!

                      – rikb
                      Mar 14 '17 at 17:56





                      Thanks for the pointer to crispy!

                      – rikb
                      Mar 14 '17 at 17:56











                      0














                      Here's another solution using path instead of the deprecated url, to create a custom version of the page and form to reset your password after following a link sent out in an email. I'm using Django 2 and Python 3.



                      In my api app folder, I've created a folder templates/account with three files inside.



                      base.html:



                      <!DOCTYPE html>
                      <html>
                      <head>
                      <title>{% block head_title %}{% endblock %}</title>
                      {% block extra_head %}
                      {% endblock %}
                      </head>
                      <body>
                      {% block body %}
                      {% block content %}
                      {% endblock %}
                      {% endblock %}
                      {% block extra_body %}
                      {% endblock %}
                      </body>
                      </html>


                      password_reset_complete.html:



                      {% extends "account/base.html" %}

                      {% block content %}

                      <h3>Password reset successful</h3>

                      <p>Your password has been changed. Please log in using the link below.</p>

                      <p><a href="/login/">Login</a></p>

                      {% endblock %}


                      password_reset_confirm.html:



                      {% extends 'account/base.html' %}

                      {% block content %}
                      {% if validlink %}
                      <h3>Enter your new password</h3>
                      <form method="post">
                      {% csrf_token %}
                      {{ form.as_p }}
                      <button type="submit">Change password</button>
                      </form>
                      {% else %}
                      <p>
                      The password reset link was invalid, possibly because it has already been used.
                      Please request a new password reset.
                      </p>
                      {% endif %}
                      {% endblock %}


                      In my api app folder, I've created a file forms.py for my custom form which extends the default SetPasswordForm form.



                      forms.py:



                      from django import forms
                      from django.contrib.auth.forms import SetPasswordForm
                      from django.utils.translation import gettext, gettext_lazy as _
                      from django.contrib.auth import password_validation

                      class SetPasswordFormCustom(SetPasswordForm):
                      new_password1 = forms.CharField(
                      label=_("New password custom"),
                      widget=forms.PasswordInput,
                      strip=False,
                      )
                      new_password2 = forms.CharField(
                      label=_("New password confirmation custom"),
                      strip=False,
                      widget=forms.PasswordInput,
                      help_text=password_validation.password_validators_help_text_html(),
                      )


                      And finally urls.py:



                      # api/urls.py
                      from django.urls import include, path
                      from django.contrib.auth import views
                      from django.conf.urls import include, url
                      from django.views.generic.base import RedirectView
                      from .forms import SetPasswordFormCustom

                      urlpatterns = [
                      ...
                      path('reset/<uidb64>/<token>/',
                      views.PasswordResetConfirmView.as_view(template_name='account/password_reset_confirm.html',
                      form_class=SetPasswordFormCustom),
                      name='password_reset_confirm'),
                      path('reset/done/', views.PasswordResetCompleteView.as_view(template_name='account/password_reset_complete.html'), name='password_reset_complete'),

                      ]


                      Note 'from .forms import SetPasswordFormCustom'. The . allows a file in the same folder to be imported.



                      My reason for doing all this is that I haven't got reset password to work in my native React frontend, so I'm having to use the Django templates for this function. I want to be able to restyle it and have links that fit with my app as nearly as possible. But this method should generally allow you to create your own custom version of a Django auth form.






                      share|improve this answer




























                        0














                        Here's another solution using path instead of the deprecated url, to create a custom version of the page and form to reset your password after following a link sent out in an email. I'm using Django 2 and Python 3.



                        In my api app folder, I've created a folder templates/account with three files inside.



                        base.html:



                        <!DOCTYPE html>
                        <html>
                        <head>
                        <title>{% block head_title %}{% endblock %}</title>
                        {% block extra_head %}
                        {% endblock %}
                        </head>
                        <body>
                        {% block body %}
                        {% block content %}
                        {% endblock %}
                        {% endblock %}
                        {% block extra_body %}
                        {% endblock %}
                        </body>
                        </html>


                        password_reset_complete.html:



                        {% extends "account/base.html" %}

                        {% block content %}

                        <h3>Password reset successful</h3>

                        <p>Your password has been changed. Please log in using the link below.</p>

                        <p><a href="/login/">Login</a></p>

                        {% endblock %}


                        password_reset_confirm.html:



                        {% extends 'account/base.html' %}

                        {% block content %}
                        {% if validlink %}
                        <h3>Enter your new password</h3>
                        <form method="post">
                        {% csrf_token %}
                        {{ form.as_p }}
                        <button type="submit">Change password</button>
                        </form>
                        {% else %}
                        <p>
                        The password reset link was invalid, possibly because it has already been used.
                        Please request a new password reset.
                        </p>
                        {% endif %}
                        {% endblock %}


                        In my api app folder, I've created a file forms.py for my custom form which extends the default SetPasswordForm form.



                        forms.py:



                        from django import forms
                        from django.contrib.auth.forms import SetPasswordForm
                        from django.utils.translation import gettext, gettext_lazy as _
                        from django.contrib.auth import password_validation

                        class SetPasswordFormCustom(SetPasswordForm):
                        new_password1 = forms.CharField(
                        label=_("New password custom"),
                        widget=forms.PasswordInput,
                        strip=False,
                        )
                        new_password2 = forms.CharField(
                        label=_("New password confirmation custom"),
                        strip=False,
                        widget=forms.PasswordInput,
                        help_text=password_validation.password_validators_help_text_html(),
                        )


                        And finally urls.py:



                        # api/urls.py
                        from django.urls import include, path
                        from django.contrib.auth import views
                        from django.conf.urls import include, url
                        from django.views.generic.base import RedirectView
                        from .forms import SetPasswordFormCustom

                        urlpatterns = [
                        ...
                        path('reset/<uidb64>/<token>/',
                        views.PasswordResetConfirmView.as_view(template_name='account/password_reset_confirm.html',
                        form_class=SetPasswordFormCustom),
                        name='password_reset_confirm'),
                        path('reset/done/', views.PasswordResetCompleteView.as_view(template_name='account/password_reset_complete.html'), name='password_reset_complete'),

                        ]


                        Note 'from .forms import SetPasswordFormCustom'. The . allows a file in the same folder to be imported.



                        My reason for doing all this is that I haven't got reset password to work in my native React frontend, so I'm having to use the Django templates for this function. I want to be able to restyle it and have links that fit with my app as nearly as possible. But this method should generally allow you to create your own custom version of a Django auth form.






                        share|improve this answer


























                          0












                          0








                          0







                          Here's another solution using path instead of the deprecated url, to create a custom version of the page and form to reset your password after following a link sent out in an email. I'm using Django 2 and Python 3.



                          In my api app folder, I've created a folder templates/account with three files inside.



                          base.html:



                          <!DOCTYPE html>
                          <html>
                          <head>
                          <title>{% block head_title %}{% endblock %}</title>
                          {% block extra_head %}
                          {% endblock %}
                          </head>
                          <body>
                          {% block body %}
                          {% block content %}
                          {% endblock %}
                          {% endblock %}
                          {% block extra_body %}
                          {% endblock %}
                          </body>
                          </html>


                          password_reset_complete.html:



                          {% extends "account/base.html" %}

                          {% block content %}

                          <h3>Password reset successful</h3>

                          <p>Your password has been changed. Please log in using the link below.</p>

                          <p><a href="/login/">Login</a></p>

                          {% endblock %}


                          password_reset_confirm.html:



                          {% extends 'account/base.html' %}

                          {% block content %}
                          {% if validlink %}
                          <h3>Enter your new password</h3>
                          <form method="post">
                          {% csrf_token %}
                          {{ form.as_p }}
                          <button type="submit">Change password</button>
                          </form>
                          {% else %}
                          <p>
                          The password reset link was invalid, possibly because it has already been used.
                          Please request a new password reset.
                          </p>
                          {% endif %}
                          {% endblock %}


                          In my api app folder, I've created a file forms.py for my custom form which extends the default SetPasswordForm form.



                          forms.py:



                          from django import forms
                          from django.contrib.auth.forms import SetPasswordForm
                          from django.utils.translation import gettext, gettext_lazy as _
                          from django.contrib.auth import password_validation

                          class SetPasswordFormCustom(SetPasswordForm):
                          new_password1 = forms.CharField(
                          label=_("New password custom"),
                          widget=forms.PasswordInput,
                          strip=False,
                          )
                          new_password2 = forms.CharField(
                          label=_("New password confirmation custom"),
                          strip=False,
                          widget=forms.PasswordInput,
                          help_text=password_validation.password_validators_help_text_html(),
                          )


                          And finally urls.py:



                          # api/urls.py
                          from django.urls import include, path
                          from django.contrib.auth import views
                          from django.conf.urls import include, url
                          from django.views.generic.base import RedirectView
                          from .forms import SetPasswordFormCustom

                          urlpatterns = [
                          ...
                          path('reset/<uidb64>/<token>/',
                          views.PasswordResetConfirmView.as_view(template_name='account/password_reset_confirm.html',
                          form_class=SetPasswordFormCustom),
                          name='password_reset_confirm'),
                          path('reset/done/', views.PasswordResetCompleteView.as_view(template_name='account/password_reset_complete.html'), name='password_reset_complete'),

                          ]


                          Note 'from .forms import SetPasswordFormCustom'. The . allows a file in the same folder to be imported.



                          My reason for doing all this is that I haven't got reset password to work in my native React frontend, so I'm having to use the Django templates for this function. I want to be able to restyle it and have links that fit with my app as nearly as possible. But this method should generally allow you to create your own custom version of a Django auth form.






                          share|improve this answer













                          Here's another solution using path instead of the deprecated url, to create a custom version of the page and form to reset your password after following a link sent out in an email. I'm using Django 2 and Python 3.



                          In my api app folder, I've created a folder templates/account with three files inside.



                          base.html:



                          <!DOCTYPE html>
                          <html>
                          <head>
                          <title>{% block head_title %}{% endblock %}</title>
                          {% block extra_head %}
                          {% endblock %}
                          </head>
                          <body>
                          {% block body %}
                          {% block content %}
                          {% endblock %}
                          {% endblock %}
                          {% block extra_body %}
                          {% endblock %}
                          </body>
                          </html>


                          password_reset_complete.html:



                          {% extends "account/base.html" %}

                          {% block content %}

                          <h3>Password reset successful</h3>

                          <p>Your password has been changed. Please log in using the link below.</p>

                          <p><a href="/login/">Login</a></p>

                          {% endblock %}


                          password_reset_confirm.html:



                          {% extends 'account/base.html' %}

                          {% block content %}
                          {% if validlink %}
                          <h3>Enter your new password</h3>
                          <form method="post">
                          {% csrf_token %}
                          {{ form.as_p }}
                          <button type="submit">Change password</button>
                          </form>
                          {% else %}
                          <p>
                          The password reset link was invalid, possibly because it has already been used.
                          Please request a new password reset.
                          </p>
                          {% endif %}
                          {% endblock %}


                          In my api app folder, I've created a file forms.py for my custom form which extends the default SetPasswordForm form.



                          forms.py:



                          from django import forms
                          from django.contrib.auth.forms import SetPasswordForm
                          from django.utils.translation import gettext, gettext_lazy as _
                          from django.contrib.auth import password_validation

                          class SetPasswordFormCustom(SetPasswordForm):
                          new_password1 = forms.CharField(
                          label=_("New password custom"),
                          widget=forms.PasswordInput,
                          strip=False,
                          )
                          new_password2 = forms.CharField(
                          label=_("New password confirmation custom"),
                          strip=False,
                          widget=forms.PasswordInput,
                          help_text=password_validation.password_validators_help_text_html(),
                          )


                          And finally urls.py:



                          # api/urls.py
                          from django.urls import include, path
                          from django.contrib.auth import views
                          from django.conf.urls import include, url
                          from django.views.generic.base import RedirectView
                          from .forms import SetPasswordFormCustom

                          urlpatterns = [
                          ...
                          path('reset/<uidb64>/<token>/',
                          views.PasswordResetConfirmView.as_view(template_name='account/password_reset_confirm.html',
                          form_class=SetPasswordFormCustom),
                          name='password_reset_confirm'),
                          path('reset/done/', views.PasswordResetCompleteView.as_view(template_name='account/password_reset_complete.html'), name='password_reset_complete'),

                          ]


                          Note 'from .forms import SetPasswordFormCustom'. The . allows a file in the same folder to be imported.



                          My reason for doing all this is that I haven't got reset password to work in my native React frontend, so I'm having to use the Django templates for this function. I want to be able to restyle it and have links that fit with my app as nearly as possible. But this method should generally allow you to create your own custom version of a Django auth form.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Jan 1 at 18:22









                          Little BrainLittle Brain

                          473411




                          473411






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f4643884%2fhow-do-i-extend-the-django-login-form%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              MongoDB - Not Authorized To Execute Command

                              How to fix TextFormField cause rebuild widget in Flutter

                              Npm cannot find a required file even through it is in the searched directory