【问题标题】:Cannot dynamically save user.is_active in Django UpdateView form_valid, or signal无法在 Django UpdateView form_valid 中动态保存 user.is_active 或信号
【发布时间】:2021-07-08 21:59:07
【问题描述】:

我有两个模型,User(扩展Abstract User 并继承is_active 字段)和Supervision 使用通用外键连接到用户。 当我们保存一个 Supervision 实例时,代码必须检查 Supervision 实例上的suspended 字段,并更新user.is_active 为相反。 我无法保存保存用户实例,因为它恢复为 True 并保存两次。 这是我来自form_valid()的代码:

suspension, created = Suspension.objects.get_or_create(
            content_type = ContentType.objects.get(app_label="myapp", model="suspension"),
            object_id = self.kwargs['pk'],
        )
suspension.reason = form.cleaned_data['reason']
suspension.suspended = form.cleaned_data['suspended']
suspension.save()
user = suspension.content_object
user.is_active = False if suspension.suspended else True
user.save()
return super().form_valid(form)

这是我的信号:

@receiver(post_save, sender=Suspension, weak=False, dispatch_uid=uuid.uuid4())
def suspend_unsuspend_user(sender, instance, **kwargs):
    from userprofile.models import User
    if isinstance(instance.content_object, User):
        user = instance.content_object
        user.is_active = instance.suspended 
        user.save()

更新:覆盖 Suspension 模型上的 save() 以更新用户实例

def save(self, *args, **kwargs):
    from userprofile.models import User
    if isinstance(self.content_object, User):
        try:
            user = self.content_object
            user.is_active = False if self.suspended else True 
            user.save()
        except:
            raise RuntimeError('Unable to find user')
    return super().save(*args, **kwargs)

没有任何效果!

在分别实现它们时,我将用户实例保存了两次,并且每次 user.is_active 恢复为 True 并保存(即用户实例上的 post_save 信号将其打印两次,最后始终为 True)。我检查了我的代码,我没有在其他任何地方触摸 user.is_active。 我也可以从管理员或外壳更改 is_active 。 怎么了?

【问题讨论】:

  • 到目前为止,我还没有成功解决这个问题。而且我无法理解原因。

标签: django django-models django-views


【解决方案1】:

问题出在form_valid() 方法中。 该问题是由在super().form_valid(form) 之前单独保存暂停的代码引起的。 代码通过将其更改为:

def form_valid(self, form):
    suspension, created = Suspension.objects.get_or_create(
            content_type = ContentType.objects.get(app_label="myapp", model="suspension"),
            object_id = self.kwargs['pk'],
        )
    suspension.reason = form.cleaned_data['reason']
    suspension.suspended = form.cleaned_data['suspended']
    form.instance = suspension # <-- here's the solution: we overwrite the form.instance and let django do its job.
    user = suspension.content_object
    user.is_active = False if suspension.suspended else True
    user.save()
    return super().form_valid(form)

【讨论】:

    猜你喜欢
    • 2016-04-30
    • 2017-06-23
    • 2023-04-06
    • 2014-02-01
    • 1970-01-01
    • 2021-09-22
    • 2021-11-23
    • 2010-09-15
    相关资源
    最近更新 更多