Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django:在用户保存时以编程方式添加组_Python_Django_Django Models_Django Users_Django Related Manager - Fatal编程技术网

Python Django:在用户保存时以编程方式添加组

Python Django:在用户保存时以编程方式添加组,python,django,django-models,django-users,django-related-manager,Python,Django,Django Models,Django Users,Django Related Manager,保存用户后,我需要确保其实例默认与组相关联 我找到了两种方法来实现这一目标: 重写模型的save()方法 models.py: from django.contrib.auth.models import AbstractUser, Group class Person(AbstractUser): def save(self, *args, **kwargs): super().save(*args, **kwargs) to_add = Gro

保存用户后,我需要确保其实例默认与组相关联

我找到了两种方法来实现这一目标:

  • 重写模型的
    save()
    方法

    models.py:

    from django.contrib.auth.models import AbstractUser, Group
    
    
    class Person(AbstractUser):
    
        def save(self, *args, **kwargs):
            super().save(*args, **kwargs)
            to_add = Group.objects.get(id=1)  # get_or_create is a better option
            instance.groups.add(to_add)
    
  • 捕获post_保存信号:

    signals.py:

    from django.conf import settings
    from django.contrib.auth.models import Group
    from django.db.models.signals import post_save
    from django.dispatch import receiver
    
    
    @receiver(
        post_save,
        sender=settings.AUTH_USER_MODEL,
    )
    def save_the_group(instance, raw, **kwargs):
        if not raw:
            to_add = Group.objects.get(id=1)  # get_or_create is a better option
            instance.groups.add(to_add)
    
这些方法在实现其目标方面是平等的吗


在Django的“良好实践”术语中有更好的吗

为了更好地理解Django的工作原理,我认为 困惑和解决办法在于:

以及:

首先保存实例以获取主键(
post\u save
然后它的所有多对多关系都基于 在
ModelForm.cleaned\u数据上

如果在
post\u save
信号期间或在 如果使用
Model.save()
方法,将从
BaseModelForm.\u save\u m2m()
,具体取决于
ModelForm.cleaned\u数据

transaction.on_commit()
——这是本文讨论的解决方案 后来,asnwer和其他一些答案启发了我 并被否决-将延迟信号的更改,直到
BaseModelForm.\u save\u m2m()
已完成其操作

虽然在某些特殊情况下,
transaction.on_commit()
,但在这种情况下,这是一种过分的杀伤力,不仅因为它会使 一种笨拙的方式(最合适的信号是
m2m\u changed
),但由于完全避免信号,因此

因此,我将尝试给出一个满足这两种情况的解决方案:

  • 如果实例是从Django Admin(ModelForm)保存的
  • 如果在不使用ModelForm的情况下保存实例
  • models.py

    from django.contrib.auth.models import AbstractUser, Group
    
    
    class Person(AbstractUser):
       def save(self, *args, **kwargs):
            super().save(*args, **kwargs)
            if not getattr(self, 'from_modelform', False):  # This flag is created in ModelForm
                <add - remove groups logic>
    
    这将在以下情况下起作用:

    >>> p = Person()
    >>> p.username = 'username'
    >>> p.password = 'password'
    >>> p.save()
    
    或与:

    from django.contrib.auth.forms import UserCreationForm
    from django.contrib.auth import get_user_model
    from django.forms.models import modelform_factory
    
    user_creationform_data = {
        'username': 'george',
        'password1': '123!trettb',
        'password2': '123!trettb',
        'email': 'email@yo.gr',
    }
    
    user_model_form = modelform_factory(
        get_user_model(),
        form=UserCreationForm,
    )
    user_creation_form = user_model_form(data=user_creationform_data)
    new_user = user_creation_form.save()
    

    旧答案

    基于一个或多个问题以及 标题为“我转向的解决方案是使用:

    您传入的函数将在 假设在调用on_commit()的地方进行的数据库写入将是 成功提交

    上述代码没有考虑到这一点

    深入调查 相关文件中提出的一个关键点是 如果在 原子事务以及依赖于
    group\u delegation()函数的结果

    @transaction.atomic
    def accept_group_invite(request, group_id):
        validate_and_add_to_group(request.user, group_id)
        # The below line would always fail in your case because the
    
    关于你的承诺 #在退出此函数之前不会调用receiver。 如果request.user.has\u perm('group\u permission'): 做某事

    更详细地描述以下约束:
    on_commit()
    成功运行

    测试 ,使用 或者 使用pytest进行测试时使用decorator


    是我如何测试此信号的示例。

    更新

    为了更好地理解Django的工作原理,我认为 困惑和解决办法在于:

    以及:

    首先保存实例以获取主键(
    post\u save
    然后它的所有多对多关系都基于 在
    ModelForm.cleaned\u数据上

    如果在
    post\u save
    信号期间或在 如果使用
    Model.save()
    方法,将从
    BaseModelForm.\u save\u m2m()
    ,具体取决于
    ModelForm.cleaned\u数据

    transaction.on_commit()
    ——这是本文讨论的解决方案 后来,asnwer和其他一些答案启发了我 并被否决-将延迟信号的更改,直到
    BaseModelForm.\u save\u m2m()
    已完成其操作

    虽然在某些特殊情况下,
    transaction.on_commit()
    ,但在这种情况下,这是一种过分的杀伤力,不仅因为它会使 一种笨拙的方式(最合适的信号是
    m2m\u changed
    ),但由于完全避免信号,因此

    因此,我将尝试给出一个满足这两种情况的解决方案:

  • 如果实例是从Django Admin(ModelForm)保存的
  • 如果在不使用ModelForm的情况下保存实例
  • models.py

    from django.contrib.auth.models import AbstractUser, Group
    
    
    class Person(AbstractUser):
       def save(self, *args, **kwargs):
            super().save(*args, **kwargs)
            if not getattr(self, 'from_modelform', False):  # This flag is created in ModelForm
                <add - remove groups logic>
    
    这将在以下情况下起作用:

    >>> p = Person()
    >>> p.username = 'username'
    >>> p.password = 'password'
    >>> p.save()
    
    或与:

    from django.contrib.auth.forms import UserCreationForm
    from django.contrib.auth import get_user_model
    from django.forms.models import modelform_factory
    
    user_creationform_data = {
        'username': 'george',
        'password1': '123!trettb',
        'password2': '123!trettb',
        'email': 'email@yo.gr',
    }
    
    user_model_form = modelform_factory(
        get_user_model(),
        form=UserCreationForm,
    )
    user_creation_form = user_model_form(data=user_creationform_data)
    new_user = user_creation_form.save()
    

    旧答案

    基于一个或多个问题以及 标题为“我转向的解决方案是使用:

    您传入的函数将在 假设在调用on_commit()的地方进行的数据库写入将是 成功提交

    上述代码没有考虑到这一点

    深入调查 相关文件中提出的一个关键点是 如果在 原子事务以及依赖于
    group\u delegation()函数的结果

    @transaction.atomic
    def accept_group_invite(request, group_id):
        validate_and_add_to_group(request.user, group_id)
        # The below line would always fail in your case because the
    
    关于你的承诺 #在退出此函数之前不会调用receiver。 如果request.user.has\u perm('group\u permission'): 做某事

    更详细地描述以下约束:
    on_commit()
    成功运行

    测试 ,使用 或者 使用pytest进行测试时使用decorator


    这是我测试这个信号的一个例子。

    有时,一些基本的、不是很复杂的位很容易将它放在模型上,其他时候,
    信号可以发送到许多想要记录他们对它感兴趣的东西上,并处理它(虽然这更可能用于
    pre_save
    stuff和
    post_save
    stuff,更可能用于更多信号:)…因此,扩展应用程序等…首选的方法(据我理解)主要取决于环境和需求。Som