Andrew
Andrew

Reputation: 55

DRF user creation with one-to-one relation

I have made a model and serializers for User and additional ones for their profile (additional info).

Model

class Profile(models.Model):
    users = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        primary_key=True,
    )
    nickname = models.CharField(max_length=10, unique=True)
    bio = models.CharField(max_length=300)
    def __str__(self):
        return self.nickname

Serializers

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username']
class ProfileSerializer(serializers.HyperlinkedModelSerializer):
    users = UserSerializer()
    class Meta:
        model = Profile
        fields = ['users', 'nickname']

It works fine for displaying it all out, but now i want to make it so i could create a new User with POST request AND also automatically assign a new empty or default Profile instance for that same User. DRF doesn't allow me to do that directly from Profile model API. Should i create a views.py function which will create a user and also create Profile for it separately or there's a built-in methods for that, so User then can update their Profile?

Upvotes: 1

Views: 649

Answers (1)

Ayush Pallav
Ayush Pallav

Reputation: 1057

You just need to override the create function of your serializer. Also, you dont really need two serializers for this purpose. Something like this will do the job for you, (change according to your fields):

class UserSerializer(serializers.Serializer):
    """
    Serializer for user details
    """
    username = serializers.CharField()
    nickname = serializers.CharField()
    bio = serializers.CharField()
    first_name = serializers.CharField()
    last_name = serializers.CharField()
    email = serializers.CharField()
    password = serializers.CharField()

    def create(self, validated_data):
        user = User(
            username=validated_data["username"],
            email=validated_data["email"]
        )
        user.set_password(validated_data["password"])
        user_id = user.save()
        Profile.objects.create(
            user_id=user.id,
            nickname=validated_data["nickname"],
            bio=validated_data["bio"]
        )
        return validated_data

Upvotes: 3

Related Questions