как передать экземпляр QuerySet в сериализатор? - PullRequest
0 голосов
/ 07 мая 2020

Я использую raw sql (с помощью orm работает) для получения продуктов, и я получаю эту ошибку

Got AttributeError when attempting to get a value for field `name` on serializer `ProductSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `tuple` 
instance.
Original exception text was: 'tuple' object has no attribute 'name'.

Это функция получения:

def get(self, request, store_id, format=None):
    with connection.cursor() as cursor:
        user = request.user
        check_auth = get_object_or_404(
            Store, id=store_id, owner_id=user.id)
        if check_auth != None:
            connection.cursor()
            cursor.execute('SELECT * FROM products')
            products = cursor.fetchall()
            serializer = ProductSerializer(products, many=True)
            return Response(serializer.data)
    raise Http404

и вот класс сериализатора:

class ProductSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
category = CategorySerializer()

class Meta:
    model = Product
    fields = ['id', 'store_id', 'name', 'summary',
              'description', 'category', 'main_image', 'price', 'offer_price', 'cost', 
    'available_quantity']

1 Ответ

1 голос
/ 07 мая 2020

Django ModelSerializer будет работать только в случае объекта QuerySet , полученного из моделей. Выполнение запросов с использованием объекта подключения приведет к появлению Python собственных типов данных, таких как List и Tuple , для которых ModelSerializer не будет работать. Итак, в этом случае cursor.fetchall() даст список tuples, и каждый кортеж состоит из реляционной строки БД. Поэтому для сериализации этих типов данных вместо ModelSerializer используйте только Serializer . Ниже фрагмент кода даст подробное представление о SerializerMethodField .

View.py

class RawQueryDjango(APIView):
    def get(self, request):
        from django.db import connection
        cursor = connection.cursor()
        cursor.execute('select * from products_usermodel')
        res = cursor.fetchall()
        serializer = RawQuerySerializer(res, many=True)
        print(serializer.data)
        return Response({'detail': serializer.data})

Serializer.py

from rest_framework.serializers import Serializer, ModelSerializer, SerializerMethodField


class RawQuerySerializer(Serializer):
    name = SerializerMethodField()
    last_name = SerializerMethodField()

    def get_name(self, obj):
        return obj[1]

    def get_last_name(self, obj):
        return obj[2]    # index value at which last_name in tuple

Это даст следующий ответ. При выполнении необработанного запроса взаимодействие с моделью не производилось.

{
    "detail": [
        {
            "name": "abc",
            "last_name": "sadfasd"
        },
        {
            "name": "asasasd",
            "last_name": "werwe"
        },
        {
            "name": "asdafa",
            "last_name": "1231weasd"
        },
        {
            "name": "sh",
            "last_name": "patil"
        }
    ]
}
...