我从这个库运行一个示例django应用程序,here is整个代码。
我想添加这个应用程序的登录部分,我想在登录视图中添加更多字段,但我真的不明白该怎么做,因为应用程序没有它自己的视图,但它只是调用模块的自己的登录视图。但是如果我想将这个库用于我自己的项目呢?我会被迫使用他们的登录视图吗?我怎么编辑它?
以下是该示例调用以处理身份验证的登录视图:
@class_view_decorator(sensitive_post_parameters())
@class_view_decorator(never_cache)
class LoginView(IdempotentSessionWizardView):
"""
View for handling the login process, including OTP verification.
The login process is composed like a wizard. The first step asks for the
user's credentials. If the credentials are correct, the wizard proceeds to
the OTP verification step. If the user has a default OTP device configured,
that device is asked to generate a token (send sms / call phone) and the
user is asked to provide the generated token. The backup devices are also
listed, allowing the user to select a backup device for verification.
"""
template_name = 'two_factor/core/login.html'
form_list = (
('auth', AuthenticationForm),
('token', AuthenticationTokenForm),
('backup', BackupTokenForm),
)
idempotent_dict = {
'token': False,
'backup': False,
}
def has_token_step(self):
return default_device(self.get_user())
def has_backup_step(self):
return default_device(self.get_user()) and \
'token' not in self.storage.validated_step_data
condition_dict = {
'token': has_token_step,
'backup': has_backup_step,
}
redirect_field_name = REDIRECT_FIELD_NAME
def __init__(self, **kwargs):
super(LoginView, self).__init__(**kwargs)
self.user_cache = None
self.device_cache = None
def post(self, *args, **kwargs):
"""
The user can select a particular device to challenge, being the backup
devices added to the account.
"""
# Generating a challenge doesn't require to validate the form.
if 'challenge_device' in self.request.POST:
return self.render_goto_step('token')
return super(LoginView, self).post(*args, **kwargs)
def done(self, form_list, **kwargs):
"""
Login the user and redirect to the desired page.
"""
login(self.request, self.get_user())
redirect_to = self.request.POST.get(
self.redirect_field_name,
self.request.GET.get(self.redirect_field_name, '')
)
if not is_safe_url(url=redirect_to, allowed_hosts=[self.request.get_host()]):
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
device = getattr(self.get_user(), 'otp_device', None)
if device:
signals.user_verified.send(sender=__name__, request=self.request,
user=self.get_user(), device=device)
return redirect(redirect_to)
def get_form_kwargs(self, step=None):
"""
AuthenticationTokenForm requires the user kwarg.
"""
if step == 'auth':
return {
'request': self.request
}
if step in ('token', 'backup'):
return {
'user': self.get_user(),
'initial_device': self.get_device(step),
}
return {}
def get_device(self, step=None):
"""
Returns the OTP device selected by the user, or his default device.
"""
if not self.device_cache:
challenge_device_id = self.request.POST.get('challenge_device', None)
if challenge_device_id:
for device in backup_phones(self.get_user()):
if device.persistent_id == challenge_device_id:
self.device_cache = device
break
if step == 'backup':
try:
self.device_cache = self.get_user().staticdevice_set.get(name='backup')
except StaticDevice.DoesNotExist:
pass
if not self.device_cache:
self.device_cache = default_device(self.get_user())
return self.device_cache
def render(self, form=None, **kwargs):
"""
If the user selected a device, ask the device to generate a challenge;
either making a phone call or sending a text message.
"""
if self.steps.current == 'token':
self.get_device().generate_challenge()
return super(LoginView, self).render(form, **kwargs)
def get_user(self):
"""
Returns the user authenticated by the AuthenticationForm. Returns False
if not a valid user; see also issue #65.
"""
if not self.user_cache:
form_obj = self.get_form(step='auth',
data=self.storage.get_step_data('auth'))
self.user_cache = form_obj.is_valid() and form_obj.user_cache
return self.user_cache
def get_context_data(self, form, **kwargs):
"""
Adds user's default and backup OTP devices to the context.
"""
context = super(LoginView, self).get_context_data(form, **kwargs)
if self.steps.current == 'token':
context['device'] = self.get_device()
context['other_devices'] = [
phone for phone in backup_phones(self.get_user())
if phone != self.get_device()]
try:
context['backup_tokens'] = self.get_user().staticdevice_set\
.get(name='backup').token_set.count()
except StaticDevice.DoesNotExist:
context['backup_tokens'] = 0
if getattr(settings, 'LOGOUT_REDIRECT_URL', None):
context['cancel_url'] = resolve_url(settings.LOGOUT_REDIRECT_URL)
elif getattr(settings, 'LOGOUT_URL', None):
warnings.warn(
"LOGOUT_URL has been replaced by LOGOUT_REDIRECT_URL, please "
"review the URL and update your settings.",
DeprecationWarning)
context['cancel_url'] = resolve_url(settings.LOGOUT_URL)
return context
我在我的一个项目中使用过这个包,许多复杂的场景都可以提出来。您可以通过多种方式自定义此视图。正如您所提到的,您需要登录表单中的额外字段,如果您只想要登录表单中的额外字段,可以使用以下方法。
步骤1使用额外字段创建您自己的登录表单
您可以创建自己的登录表单,继承自django的内置表单,也可以从用于登录的表单继承。在其中添加额外的字段。
class YourLoginForm(AuthenticationForm):
pass
# your extra fields and functionality here
步骤2从包中继承登录视图并使用您的表单
您必须创建从包的内置登录视图继承的登录视图,并添加您的登录表单以及其他类似的登录表单
from TWO_FACTOR_AUTU import LoginView
class YourLoginView(LoginView):
form_list = (
('auth', YourLoginForm),
('token', AuthenticationTokenForm),
('backup', BackupTokenForm),
)
使用此视图和适当的路由来处理身份验证。希望这可以帮助