【问题标题】:Create object only if other object is successfully created仅当成功创建其他对象时才创建对象
【发布时间】:2020-02-27 11:43:57
【问题描述】:

我对 Django 很陌生,不熟悉这种情况的最佳实践(在任何框架/语言中,而不仅仅是 python/django)。

情况是,当用户第一次在我的网站上注册时,如果它不存在,我想为他们创建一个“组织”,然后为他们创建一个引用该组织的用户。我从不想插入一个没有另一个,但我需要先创建组织,以便可以为每个用户保存组织 UUID。现在,即使创建用户时出现问题,仍会创建组织。这显然是一个问题,因为那时我有一个没有附加用户的组织。

我不完全知道如何在创建组织之前检查用户是否已正确创建,但这些方面的事情似乎是我需要做的。在组织对象创建上使用 commit=false 似乎不起作用,因为我需要获取 UUID。所以我不确定最好的方法。

我正在覆盖流行的认证包django-allauth的序列化程序中的save方法

models.py

class Organization(models.Model):
  alphanumeric_plus_underscore = RegexValidator(r'^[\w]+$', 'Only alphanumeric characters are allowed.')
  id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)  # pylint: disable=invalid-name
  name = models.CharField(max_length=20, unique=True, validators=[alphanumeric_plus_underscore, MinLengthValidator(4)])
  logo = models.FileField(upload_to='files/organization_logos/', null=True, blank=True)

class User(AbstractBaseUser):
  id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)  # pylint: disable=invalid-name
  first_name = models.CharField(_('First Name'), max_length=50)
  last_name = models.CharField(_('Last Name'), max_length=50)
  email = models.EmailField(_('Email address'), unique=True)
  organization = models.ForeignKey(Organization, blank=False, null=False, on_delete=models.DO_NOTHING)

serializers.py

def save(self, request):
    # generate organization object
    organization_data = self.validated_data.pop('organization')
    organization = Organization.objects.create(**organization_data)
    self.validated_data['organization'] = organization

    adapter = get_adapter()
    user = adapter.new_user(request)
    self.cleaned_data = self.get_cleaned_data()
    user.organization = organization #self.cleaned_data.get('organization')
    adapter.save_user(request, user, self)
    self.custom_signup(request, user)
    setup_user_email(request, user, [])

    return user

非常感谢任何指导。

【问题讨论】:

    标签: python django django-models django-views django-serializer


    【解决方案1】:

    您必须将信号添加到您的用户模型中。像这样:

    @receiver(post_save, sender=settings.AUTH_USER_MODEL)
    def create_organization(sender, instance=None, created=False, **kwargs):
        if created:
            organization.objects.create(user=instance)
    

    这对我有用。当我需要在用户创建时创建一些对象时。它在创建用户实例后称为自动。

    【讨论】:

      【解决方案2】:

      如果不存在,我想为他们创建一个“组织”

      使用Queryset.get_or_create 获取或创建组织。

      将所有这些都包含在 transaction 中。

      from django.db import transaction
      
      
      with transaction.atomic():
          organization, created = Organization.objects.get_or_create(**organization_data)
          # Try creating user and if that fails, raise an Exception.
          # This way organisation created in the transaction is rolled back.
      

      【讨论】:

      • 谢谢!在这种情况下,我不需要 get_or_create,因为我从不想更新或返回现有记录,但原子方法有所帮助。
      【解决方案3】:

      原子性是数据库事务的定义属性。 atomic 允许我们创建一个代码块,在其中保证数据库的原子性。如果代码块成功完成,则将更改提交到数据库。如果出现异常,则回滚更改。

      from django.db import transaction
      
      def viewfunc(request):
          # This code executes in autocommit mode (Django's default).
          do_stuff()
      
          with transaction.atomic():
              # This code executes inside a transaction.
              do_more_stuff()
      

      更多详情refer到给定的链接。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-24
        • 2017-04-22
        • 2015-03-12
        • 2011-10-08
        • 1970-01-01
        • 1970-01-01
        • 2023-02-20
        • 2018-03-10
        相关资源
        最近更新 更多