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
- 重写模型的
方法 models.py:save()
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
),但由于完全避免信号,因此
因此,我将尝试给出一个满足这两种情况的解决方案:
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