Reputation: 1241
I have models User
and Role
. User model has foreign key role
from model Role
as show below.
User Model
class User(model.Model):
first_name = models.CharField(max_length=255, blank=False)
role = models.ForeignKey(Role, on_delete=models.CASCADE, blank=False)
Role Model
class Role(models.Model):
role_name = models.CharField(max_length=255, blank=False, unique=True)
I wrote a serializer for model User
.
class User(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
role = serializers.IntegerField(required=True)
I am using APIView
to get the list of all the users. I want get()
method of APIVIew
to a return list of all the user with role_name
instead of role_id
like this -
[
{
"first_name":"Name",
"role": "Admin"
},
{
"first_name":"Name",
"role": "Merchant"
}
]
views.py
class ListUsers(APIView):
def get(self, request, formate=None):
admin_users = User.objects.all().values('first_name', 'role')
return Response(admin_users)
My ListUsers(APIView)
class returns the list like this -
[
{
"first_name":"Name",
"role":1
},
{
"first_name":"Name",
"role":2
}
]
I want my APIView to return list of users and each object should have role_name
instead of role_id
. I don't want to use ModelSerializer
. Also, I have an APIView()
class which create an object for model User
and it uses the same serializer. I want a solution which would not affect create user functionality.
Upvotes: 2
Views: 2612
Reputation: 3378
Use the below serializer for getting the output you need.
This serializer can be used for creation too but instead of sending the role_id you have to send the role_name in the role field.
You did not specify what is the structure of your POST data so I am assuming it to be the same as the output.
class User(serializers.Serializer):
first_name = serializers.CharField(max_length=255, allow_blank=False)
role = serializers.CharField(max_length=255, allow_blank=False)
def create(self, validated_data):
role = get_object_or_404(Role.objects.all(), role_name=validated_data['role'])
user = User.objects.create(first_name=validated_data['first_name'], role=role)
return user
def update(self, instance, validated_data):
role = get_object_or_404(Role.objects.all(), role_name=validated_data['role'])
instance.first_name = validated_data['first_name']
instance.role = role
instance.save()
return instance
def to_representation(self, instance):
ret = {
"first_name": instance.first_name,
"role": instance.role.role_name,
}
return ret
Upvotes: 0
Reputation: 1929
class ListUsers(APIView):
def get(self, request, formate=None):
users = Userdrf.objects.all().values('first_name', 'role__role_name')
return Response(users)
[
{'first_name': 'asd', 'role__role_name': 'admin'},
{'first_name': 'asd', 'role__role_name': 'not_admin'}
]
class User(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
my_role = serializers.SerializerMethodField()
class Meta:
model = User
fields = (
'id',
'my_role'
)
def get_my_role(self, obj):
return {
'role': obj.user.role.role_name,
}
BTW-
Upvotes: 0
Reputation: 850
First of all you are not using your serializer. In order to use your serializer you have to use ListAPIView instead of APIView
and set its serailizer_class
to the serializer you have implemented and set its queryset
or implement its get_queryset
. The list of lists is due to your code nesting the objects within a set:
return Response({admin_users})
But as for returning role name instead of role id take look at SlugRelatedField which is there specifically for your use case.
Upvotes: 2