Как получить значение внешнего ключа с помощью класса DRF Serializer () - PullRequest
2 голосов
/ 19 июня 2020

У меня есть модели User и Role. Модель пользователя имеет внешний ключ role от модели Role, как показано ниже.

Модель пользователя

class User(model.Model):

    first_name = models.CharField(max_length=255, blank=False)
    role = models.ForeignKey(Role, on_delete=models.CASCADE, blank=False)

Ролевая модель

class Role(models.Model):
    
    role_name = models.CharField(max_length=255, blank=False, unique=True)

Я написал сериализатор для модели User.

class User(serializers.Serializer):

    id = serializers.IntegerField(read_only=True)
    role = serializers.IntegerField(required=True)

Я использую APIView, чтобы получить список всех пользователей. Я хочу get() метод APIVIew в список возврата всех пользователей с role_name вместо role_id, как это -

[
    {
        "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)

Мой ListUsers(APIView) класс возвращает такой список -

[
    {
        "first_name":"Name",
        "role":1
    },
    {
        "first_name":"Name",
        "role":2
    }
]

Я хочу, чтобы мой APIView возвращал список пользователей, и каждый объект должен иметь role_name вместо role_id. Я не хочу использовать ModelSerializer. Кроме того, у меня есть класс APIView(), который создает объект для модели User и использует тот же сериализатор. Мне нужно решение, которое не повлияет на функциональность создания пользователей.

Ответы [ 3 ]

2 голосов
/ 19 июня 2020

Прежде всего, вы не используете сериализатор. Чтобы использовать ваш сериализатор, вы должны использовать ListAPIView вместо APIView и установить его serailizer_class на реализованный вами сериализатор и установить его queryset или реализовать его get_queryset. Список списков связан с тем, что ваш код встраивает объекты в набор:

    return Response({admin_users})

Но что касается возврата имени роли вместо идентификатора роли, обратите внимание на SlugRelatedField , который предназначен специально для ваш вариант использования.

0 голосов
/ 25 июня 2020

Используйте указанный ниже сериализатор для получения нужного вам результата.

Этот сериализатор также можно использовать для создания, но вместо отправки role_id вам нужно отправить role_name в поле роли.

Вы не указали, какова структура ваших данных POST, поэтому я предполагаю, что она такая же, как и вывод.

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       
0 голосов
/ 24 июня 2020

Во-первых, пожалуйста, не используйте «id» в качестве имени поля, это неправильно!

Ответ 1: простой способ сделать это:

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'}
]

Ответ 2: Другой способ - подключить сериализатор к представлению и немного изменить его, например:

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-

...