Search code examples
pythondjangouser-profile

Why do we have to save instance of a profile when that profile is already created and saved?


I am following a tutorial in Django and I have some problem understanding code below:

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

# why do we need to save instance? 'Profile.objects.create' already created and save that for us
@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
    instance.profile.save()

That means if a user create an account or sign up to the website, using signals a profile will be created automatically associated to that user.

The question is that why do we need to save the instance of the profile because Profile.objects.create(user=instance) has already created and saved that instance simultaneously.

Even if I omit the second block of above code it will still work fine:

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

What am I missing here or I don't understand or is it that we don't need that second block? Please help me understand this and thank you in advance.


Solution

  • You should take it up with the authors of that tutorial.

    The reasoning behind this is not for creation, but for when you're updating. For example, you might do this to update an existing user and their profoile:

    user = request.user
    user.last_name = 'Smith'
    user.profile.info_field = 'Some details'
    user.save()
    

    There, you've called save on the user, but without that second signal you haven't saved the linked profile. The signal is intended to ensure that when you call user.save(), the profile is also saved automatically.

    But this isn't a pattern that I like at all, and don't recommend it. If you're changing an object, you are responsible for saving it - in the code above you should call user.profile.save() rather than relying on a signal.