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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With