Как написать сериализатор для объединенной модели? - PullRequest
3 голосов
/ 01 октября 2019

Я применил объединение к двум таблицам со следующим запросом,

VIEWS.PY

class performance(viewsets.ModelViewSet):

    queryset = Leads.objects.select_related('channelId'
        ).values("channelId__channelName").annotate(tcount=Count('channelId'))

    serializer_class = teamwise_lead_performance_serializer

, но я не могу перехватить ответ с помощью этого сериализатора,

SERIALIZER.PY

class channel_serializer(serializers.ModelSerializer):
    class Meta:
        model = Channels
        fields = ['channelName']


class performance_serializer(serializers.ModelSerializer):
    tcount = serializers.IntegerField()
    channel = channel_serializer(many=True, read_only=True)

    class Meta:
        model = Leads
        fields = ['tcount', 'channel']

фактические результаты:

[
    {
        "tcount": 88
    },
    {
        "tcount": 25
    },
    {
        "tcount": 31
    },
    ...
]

ожидаемые результаты:

[
    {
        "channelName": "abc",
        "tcount": 88
    },
    {
        "channelName": "def",
        "tcount": 25
    },
    {
        "channelName": "ghi",
        "tcount": 31
    },
    ...
]

я пробовалследующее:

Как объединить две модели в django-rest-framework

Models.py

class Channels(models.Model):
    id = models.IntegerField(primary_key=True)
    channelName = models.CharField(max_length=20, default=None)

    class Meta:
        db_table = "table1"

class Leads(models.Model):
    id = models.IntegerField(primary_key=True)
    channelId = models.ForeignKey(Channels, on_delete=models.CASCADE, db_column='channelId')

    class Meta:
        db_table = "table2"

почему он не получает channelName в ответ? что я тут не так делаю? Спасибо за ваши предложения

Редактировать

Когда я пытаюсь ответить на вопрос Мерена, я получаю следующую ошибку:

KeyError при попытке получить значение для поля channelName on serializer performance_serializer . Поле сериализатора может иметь неправильное имя и не соответствовать ни одному атрибуту или ключу в экземпляре dict. Первоначальный текст исключения был: 'channelId'.

Ответы [ 2 ]

3 голосов
/ 06 октября 2019

Мне удалось заставить его работать со следующим:

class performance_serializer(serializers.ModelSerializer):
    tcount = serializers.IntegerField()
    channelName = serializers.CharField(source='channelId__channelName')

    class Meta:
        model = Leads
        fields = ['tcount', 'channelName']

class performance(viewsets.ModelViewSet):
    queryset = Leads.objects.select_related('channelId'
        ).values("channelId__channelName").annotate(tcount=Count('channelId'))
    serializer_class = performance_serializer

При этом я настоятельно рекомендую вам следовать как PEP , так и Django по именованиюусловные обозначения.

Вот как будет выглядеть ваш код в соответствии с указанными условными обозначениями:

class Channel(models.Model):
    id = models.IntegerField(primary_key=True)
    channel_name = models.CharField(max_length=20, default=None)

class Lead(models.Model):
    id = models.IntegerField(primary_key=True)
    channel = models.ForeignKey(Channel, on_delete=models.CASCADE)

class PerformanceSerializer(serializers.ModelSerializer):
    channel_count = serializers.IntegerField()
    channel_name = serializers.CharField(source='channel__channel_name')

    class Meta:
        model = Lead
        fields = ['channel_count', 'channel_name']

class PerformanceViewSet(viewsets.ModelViewSet):
    queryset = Lead.objects.select_related('channel'
        ).values("channel__channel_name").annotate(channel_count=Count('channel'))
    serializer_class = PerformanceSerializer

Основной вывод заключается в , а не изменении имени по умолчанию вашего ForeignKey столбцы! Это делает работу со связанными моделями гораздо более запутанной и, возможно, является причиной вашей проблемы в первую очередь (хотя я не смог доказать это).

1 голос
/ 01 октября 2019

Если вы хотите получить только имя канала, тогда лучше использовать

channelName = serializers.CharField(source='channelId.channelName') 

Также, пожалуйста, исправьте ваш синтаксис. Вы не соблюдаете стандарты pep8.

РЕДАКТИРОВАТЬ

class PerformanceSerializer(serializers.ModelSerializer):
    tcount = serializers.IntegerField()
    channelName = serializers.CharField(source='channelId.channelName') 

    class Meta:
        model = Leads
        fields = ['tcount', 'channelName']

РЕДАКТИРОВАТЬ

queryset = Leads.objects.select_related('channelId').values("channelId__channelName").annotate(tcount=Count('channelId'))

Удалить .values("channelId__channelName") часть от вашего взгляда

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...