类型错误:'<' not supported between instances of 'CombinedExpression' and 'int' when trying to implement the post_save signal with django-axes

问题描述 投票:0回答:1

我正在尝试创建一个信号,当用户登录时未能提供正确的凭据时,该信号会发送电子邮件通知访问尝试。访问尝试由 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()
,但我不知道还能做什么。有没有办法比较这两个值?

python django django-signals
1个回答
0
投票

出现此错误是因为

instance.failures_since_start
不返回整数,而是返回
CombinedExpression

要解决此问题,您需要确保在与

failures_since_start
进行比较之前将
failure_limit
计算为整数。

尝试以下操作:

failures = int(instance.failures_since_start)
failure_limit = int(AXES_FAILURE_LIMIT)
© www.soinside.com 2019 - 2024. All rights reserved.