27👍
Indeed, Django Rest Framework can’t handle this job with nested relationships then you have to implement these methods yourself. I will give you some example of what your code should look like.
Your view :
class UserList(generics.ListCreateAPIView):
permission_classes = (IsAuthenticatedOrWriteOnly,)
serializer_class = UserSerializer
def post(self, request, format=None):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Now, the save
method of your serializer will call a create
method when you want to create an object and update
method when you want to update an object. So let’s implement the create
method of your UserSerializer
which will create the profile and the user. Here is a simple example of what your UserSerializer
should look like :
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer(required=True)
class Meta:
model = User
fields = ('url', 'email', 'profile', 'created',)
def create(self, validated_data):
# create user
user = User.objects.create(
url = validated_data['url'],
email = validated_data['email'],
# etc ...
)
profile_data = validated_data.pop('profile')
# create profile
profile = Profile.objects.create(
user = user
first_name = profile_data['first_name'],
last_name = profile_data['last_name'],
# etc...
)
return user
As I said, this is an example, you have to complete it to do what you want to do but now, you know how to do it 🙂 To define the behavior during an update, implement an update
method.
3👍
This might be late but why not bypass drf entirely and relegate profile creation trigger to models using signals like so:
models.py
class User(AbstractBaseUser):
pass
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='customer_profile')
country = models.CharField(blank=True, max_length=250)
signals.py
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(
user = instance
)
this basically triggers a corresponding profile row creation once a user has been created via any means; admin, drf etc.
then you can use serializers to update the data.
hope this helps anyone else stumbling here
- Filter a django QuerySet with the query from another QuerySet: Possible?
- Is it a good practice to use serializer as query parameters validators?