我正在尝试创建一个信号,当用户登录时未能提供正确的凭据时,该信号会发送电子邮件通知访问尝试。访问尝试由 django-axes 包跟踪。如果达到
failure_limit
,则使用另一个信号。比较两个值可以确定当前是否使用该信号。
TypeError 发生在
failures = instance.failures_since_start
。
from axes.models import AccessAttempt
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.mail import mail_admins
from django.template import loader
from tajnanorka.settings import AXES_FAILURE_LIMIT
@receiver(post_save, sender=AccessAttempt)
def login_attempt_email(sender, instance, **kwargs):
def _render_email_message(context):
template = loader.get_template("foo.html")
return template.render(context)
failures = instance.failures_since_start
failure_limit = int(AXES_FAILURE_LIMIT)
context = dict(
failures_since_start = failures,
)
subject = 'bar'
message = _render_email_message(context)
if failures < failure_limit:
mail_admins(
subject,
message,
fail_silently=False,
html_message = message
)
访问尝试模型:
class AccessBase(models.Model):
user_agent = models.CharField(_("User Agent"), max_length=255, db_index=True)
ip_address = models.GenericIPAddressField(_("IP Address"), null=True, db_index=True)
username = models.CharField(_("Username"), max_length=255, null=True, db_index=True)
http_accept = models.CharField(_("HTTP Accept"), max_length=1025)
path_info = models.CharField(_("Path"), max_length=255)
attempt_time = models.DateTimeField(_("Attempt Time"), auto_now_add=True)
class Meta:
app_label = "axes"
abstract = True
ordering = ["-attempt_time"]
class AccessAttempt(AccessBase):
get_data = models.TextField(_("GET Data"))
post_data = models.TextField(_("POST Data"))
failures_since_start = models.PositiveIntegerField(_("Failed Logins"))
def __str__(self):
return f"Attempted Access: {self.attempt_time}"
class Meta:
verbose_name = _("access attempt")
verbose_name_plural = _("access attempts")
unique_together = [["username", "ip_address", "user_agent"]]
这是整个回溯:
Traceback (most recent call last):
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\core\handlers\exception.py", line 42, in inner
response = await get_response(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\core\handlers\base.py", line 253, in _get_response_async
response = await wrapped_callback(
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\views\generic\base.py", line 104, in view
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\utils\decorators.py", line 48, in _wrapper
return bound_method(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\views\decorators\debug.py", line 143, in sensitive_post_parameters_wrapper
return view(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\utils\decorators.py", line 48, in _wrapper
return bound_method(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\utils\decorators.py", line 188, in _view_wrapper
result = _process_exception(request, e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\utils\decorators.py", line 186, in _view_wrapper
response = view_func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\utils\decorators.py", line 48, in _wrapper
return bound_method(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\views\decorators\cache.py", line 80, in _view_wrapper
response = view_func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\contrib\auth\views.py", line 88, in dispatch
return super().dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\views\generic\base.py", line 143, in dispatch
return handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\views\generic\edit.py", line 150, in post
if form.is_valid():
^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\forms\forms.py", line 197, in is_valid
return self.is_bound and not self.errors
^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\forms\forms.py", line 192, in errors
self.full_clean()
^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\forms\forms.py", line 328, in full_clean
self._clean_form()
^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\forms\forms.py", line 349, in _clean_form
cleaned_data = self.clean()
^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django_otp\forms.py", line 272, in clean
self.cleaned_data = super().clean()
^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\contrib\auth\forms.py", line 250, in clean
self.user_cache = authenticate(
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\views\decorators\debug.py", line 75, in sensitive_variables_wrapper
return func(*func_args, **func_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\contrib\auth\__init__.py", line 91, in authenticate
user_login_failed.send(
^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\dispatch\dispatcher.py", line 189, in send
response = receiver(signal=self, sender=sender, **named)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\axes\signals.py", line 28, in handle_user_login_failed
AxesProxyHandler.user_login_failed(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\axes\helpers.py", line 614, in inner
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\axes\handlers\proxy.py", line 119, in user_login_failed
return cls.get_implementation().user_login_failed(
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\axes\handlers\database.py", line 216, in user_login_failed
attempt.save()
^^^^^^^^^^^^^^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\db\models\base.py", line 822, in save
self.save_base(
^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\db\models\base.py", line 924, in save_base
post_save.send(
^
File "C:\Users\desp\anaconda3\envs\tajnanorka-venv\Lib\site-packages\django\dispatch\dispatcher.py", line 189, in send
response = receiver(signal=self, sender=sender, **named)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\desp\Documents\Django-projects\projekt-tajnanorka\norkamarzen\signals.py", line 108, in login_attempt_email
if failures < failure_limit:
^^^^^^^^^^^^^^^^^^^^^^^^
Exception Type: TypeError at /accounts/login/
Exception Value: '<' not supported between instances of 'CombinedExpression' and 'int'
我尝试将
failures
转换为int()
,但我不知道还能做什么。有没有办法比较这两个值?
出现此错误是因为
instance.failures_since_start
不返回整数,而是返回 CombinedExpression
。
要解决此问题,您需要确保在与
failures_since_start
进行比较之前将 failure_limit
计算为整数。
尝试以下操作:
failures = int(instance.failures_since_start)
failure_limit = int(AXES_FAILURE_LIMIT)