Create object only if other object is successfully created

回眸只為那壹抹淺笑 提交于 2021-02-18 19:09:57

问题


I am fairly new to Django and unfamiliar with the best practices for this situation (in any framework/language, not just python/django).

The situation is that when a user first registers on my site, I want to create an "organization" for them if it doesn't exists, and then subsequently create a user for them, which references the organization. I never want to insert one without the other, but I need to create the organization first so that the organization UUID can be saved for each user. Right now, organizations will still be created even if there is an issue with the creation of the user. This is obviously a problem because then I have an organization with no users attached.

I don't exactly know how to check that the user will be properly created before creating the organization, but something along these lines seems to be what I need to do. Using commit=false on the organization object creation wouldn't seem to work because I need to get the UUID. So I am not sure the best way to proceed.

I am overwriting the save method in the serializer of the popular authentication package django-allauth

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

Any guidance is much appreciated.


回答1:


Atomicity is the defining property of database transactions. atomic allows us to create a block of code within which the atomicity on the database is guaranteed. If the block of code is successfully completed, the changes are committed to the database. If there is an exception, the changes are rolled back.

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()

for more detail refer to the given link.




回答2:


I want to create an "organization" for them if it doesn't exists

Use Queryset.get_or_create to get or create the organisation.

Wrap all of this in a 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.



回答3:


you must add signal into your user model . like this :

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

this is work for me. when I need to create some object when the user created. it's called automatic after user instance created.



来源:https://stackoverflow.com/questions/58654790/create-object-only-if-other-object-is-successfully-created

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!