Django rest framework extended user profile
Question: I recently discovered DRF and I'm lost with the quantity of views, viewsets
and other possibilities.

I have a Python3/Django 1.8 application with an extended user profile:

    
    
    from django.db import models
    from django.contrib.auth.models import User
    from django.utils.translation import ugettext_lazy as _
    
    
    class Profile(models.Model):
        GENDER = (
            ('male', _('MALE')),
            ('female', _('FEMALE')),
        )
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        bio = models.CharField(default='', max_length=500, null=True, blank=True)
        gender = models.CharField(max_length=10, choices=GENDER, null=True, blank=True)
        city = models.CharField(default='', max_length=30, null=True, blank=True)
        country = models.CharField(default='', max_length=30, null=True, blank=True)
    

I would like to allow external mobile applications connected with oauth2/token
Bearer to **get the current connected user's profile** through the api and
**editing it** using those routes:

GET or PUT /api/profile GET or PUT /api/user

My first intention was using only one route for manipulate both models
(through /api/profile) but I failed and I'm not sure if it's a good practice
to mix two models behind one route.

I tried lot of things. My last attempt was to get the profile like this:

    
    
    class UserSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = User
            fields = ('url', 'username', 'password', 'email', 'groups')
    
        password = serializers.CharField(write_only=True)
    
    
    class UserViewSet(viewsets.ModelViewSet):
        @list_route(methods=['get', 'post'], permission_classes=[permissions.IsAuthenticated])
        def profile(self, request):
            u = User.objects.filter(pk=request.user.pk)[0]
            p = Profile.objects.filter(user=u)[0]
            return Response({"id": u.id, "first_name": u.first_name, "last_name": u.last_name, "email": u.email,
                         "city": p.city, "country": p.country, "bio": p.bio})
    
        permission_classes = [permissions.IsAuthenticated]
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
    
    router = routers.DefaultRouter()
    router.register(r'users', UserViewSet)
    

Problem is: I'm failed trying to implement the same thing for PUT requests.
Furthermore I would like to do the security and defensive coding part on the
API side and in this situation I don't even using the serializers.

Could you guys help me to find the right thing to do? Do you have any tips,
suggestions?

Cheers


Answer: I think this is what you want:

    
    
    class ProfileSerializer(serializers.ModelSerializer):
        class Meta:
            model = Profile
            fields = ('bio', 'gender', 'city', 'country')
    
    
    class UserSerializer(serializers.ModelSerializer):
    
        profile = ProfileSerializer()
    
        class Meta:
            model = User
            fields = ('url', 'username', 'password', 'email', 'groups', 'profile')
    

Or if you want it flat:

    
    
    class UserSerializer(serializers.ModelSerializer):
    
        bio = serializers.CharField(source='profile.bio')
        gender = serializers.CharField(source='profile.gender')
        #same for the others
    
        class Meta:
            model = User
            fields = ('url', 'username', 'password', 'email', 'groups', 'bio', 'gender')
    

I didn't test it, but should be close to what you want, or close to it at
least.

