如何使用我自己的自定义表单覆盖django-rest-auth中的表单? [英] How to override a form in django-rest-auth with my own custom form?

查看:175
本文介绍了如何使用我自己的自定义表单覆盖django-rest-auth中的表单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用django-rest-auth,并且尝试通过覆盖表单的一种方法来修复密码重置视图中的错误。尽管我已经成功地使用另一种django-rest-auth表单完成了类似的操作,但是我无法在此表单上使用它。

I'm using django-rest-auth and I am trying to fix a bug in the password reset view by overwriting one of the form's methods. Although I've successfully done something similar with a different django-rest-auth form, I can't make it work on this one. Whatever I do, the old form is used.

api / 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
from .forms import PasswordResetFormCustom

urlpatterns = [
    path('password/reset/',
        views.PasswordResetView.as_view(form_class=PasswordResetFormCustom),
        name='rest_password_reset'),
    path('rest-auth/', include('rest_auth.urls')),
    path('rest-auth/registration/', include('rest_auth.registration.urls')),
    path('users/', include('users.urls')),
    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'),
    path('content/', include('lists.endpoints')),
    # content is a path for lists, items etc found in the lists app
]

forms.py

from django import forms
from django.contrib.auth.forms import SetPasswordForm
from django.contrib.auth import (
    authenticate, get_user_model, password_validation,
)
from django.utils.translation import gettext, gettext_lazy as _
#from django.contrib.auth import password_validation

from django.contrib.auth.forms import PasswordResetForm
UserModel = get_user_model()

class SetPasswordFormCustom(SetPasswordForm):
    new_password1 = forms.CharField(
        label=_("New password"),
        widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'Password'}),
        strip=False,
    )
    new_password2 = forms.CharField(
        label=_("Confirm new password"),
        strip=False,
        widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'Confirm password'}),
        help_text=password_validation.password_validators_help_text_html(),
    )

class PasswordResetFormCustom(PasswordResetForm):
    def get_users(self, email):
        print('using custom form');
        """Given an email, return matching user(s) who should receive a reset.

        This allows subclasses to more easily customize the default policies
        that prevent inactive users and users with unusable passwords from
        resetting their password.
        """
        active_users = UserModel._default_manager.filter(**{
            '%s__iexact' % UserModel.get_email_field_name(): email,
            'is_active': True,
        })

        if not active_users:
            raise forms.ValidationError(_("The e-mail address is not assigned to any user account"),
                code='invalid')
        return (u for u in active_users if u.has_usable_password())

因此,我不明白的是没有使用PasswordResetFormCustom及其对active_users的检查。当我请求密码重置电子邮件且未执行检查时,使用自定义表单行未打印在服务器日志中。

So, what I can't figure out is that PasswordResetFormCustom with its check for active_users, is not used. The line "using custom form" is not printed in the server log when I request a password reset email, and the check is not performed.

我的其他自定义表单PasswordResetConfirmView起作用没错。

My other custom form PasswordResetConfirmView works fine.

没有错误,所以并不是进口不正确。

There are no errors so it isn't that the imports are incorrect.

任何想法我可以自定义get_users方法,而无需编辑django-rest-auth文件?

Any idea how I can customise the get_users method without having to edit the django-rest-auth file?

感谢您的帮助!

编辑:我将yofee的代码放入了一个serializers.py文件中,而且我还不得不在urls.py中修复我的url路径的顺序。

I put yofee's code into a file serializers.py, and also I had to fix the order of my url paths in urls.py. Now it works!

urlpatterns = [
...
path('rest-auth / password / reset /',PasswordResetView.as_view( )),
路径('rest-auth /',include('rest_auth.urls')),
...
]

urlpatterns = [ ... path('rest-auth/password/reset/', PasswordResetView.as_view()), path('rest-auth/', include('rest_auth.urls')), ... ]

重置路径必须在包含之前。

reset path must come before the include.

推荐答案

解决方案应该是


  1. 在您的视图中未设置 PasswordResetFormCustom ,但在序列化程序中

  2. 使用 rest_auth PasswordResetView (不是Django的)

  1. not set PasswordResetFormCustom in your view but in your serializer
  2. use the rest_auth's PasswordResetView (not Django's)

示例:

from django.contrib.auth.forms import PasswordResetForm as DjangoPasswordResetForm
from rest_auth.serializers import (
    PasswordResetSerializer as RestAuthPasswordResetSerializer
)
from rest_auth.views import PasswordResetView as RestAuthPasswordResetView
from django.utils.translation import ugettext_lazy as _
from rest_framework.exceptions import ValidationError

class PasswordResetForm(DjangoPasswordResetForm):
    def get_users(self, email):
        users = tuple(super().get_users(email))
        if users:
            return users
        msg = _('"{email}" was not found in our system.')
        raise ValidationError({'email': msg.format(email=email)})


class PasswordResetSerializer(RestAuthPasswordResetSerializer):
    password_reset_form_class = PasswordResetForm


class PasswordResetView(RestAuthPasswordResetView):
    serializer_class = PasswordResetSerializer

    def __init__(self, *args, **kwargs):
        """Prints the name of the class if it is used."""
        print(self.__class__.__name__)
        super().__init__(*args, **kwargs)

这篇关于如何使用我自己的自定义表单覆盖django-rest-auth中的表单?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆