Django 如何为联接模型编写序列化程序?

Django 如何为联接模型编写序列化程序?,django,django-models,django-rest-framework,django-serializer,Django,Django Models,Django Rest Framework,Django Serializer,我已使用以下查询在两个表上应用了join 视图.PY class performance(viewsets.ModelViewSet): queryset = Leads.objects.select_related('channelId' ).values("channelId__channelName").annotate(tcount=Count('channelId')) serializer_class = teamwise_lead_perform

我已使用以下查询在两个表上应用了join

视图.PY

class performance(viewsets.ModelViewSet):

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

    serializer_class = teamwise_lead_performance_serializer
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']
但我无法使用此序列化程序捕获响应

序列化程序.PY

class performance(viewsets.ModelViewSet):

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

    serializer_class = teamwise_lead_performance_serializer
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
    },
    ...
]
我尝试了以下方法:

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

型号.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
的响应? 我做错了什么? 谢谢你的建议

编辑 当我尝试Mehren的答案时,我得到以下错误:

尝试获取序列化程序性能\u序列化程序上的字段channelName的值时出现键错误。序列化程序字段的名称可能不正确,并且与dict实例上的任何属性或键都不匹配。原始异常文本为:“channelId”


如果您只想获得channelName,那么最好使用

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'))
编辑

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\uu channelName”)
部分

我设法使其与以下内容一起工作:

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
话虽如此,我还是强烈建议您遵循命名和命名惯例

下面是您的代码的外观,如下所述:

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
列的默认名称!这使得使用相关模型变得更加混乱,并且可能是您出现问题的首要原因(尽管我无法证明这一点)

如果我添加
channelName=serializers.CharField(source='channel.name')
?在performance_serializer中,它为我提供了
字段“channel”已在serializer performance_serializer上声明,但尚未包含在“fields”选项中。
。。。。。。。我在问题中添加了模型我编辑了答案。基本上,对于DRF序列化程序,您手动定义的字段也必须存在于Meta.fields中。现在,在尝试获取序列化程序“performance\u serializer”上的字段“channelName”的值时,我遇到了
get keyrorm。\n序列化程序字段的名称可能不正确,并且与“dict”实例上的任何属性或键都不匹配。\n原始异常文本为:“频道”。
我已经根据您的型号定义编辑了答案。希望有帮助!试图获取序列化程序“performance\u serializer”上字段“channelName”的值时,geting
get-KeyError仍然存在。序列化程序字段的名称可能不正确,并且与“dict”实例上的任何属性或键都不匹配。原始异常文本为:“channelId”。
您在
Lead
模型中有一个输入错误,在
channel
字段中:相关型号名称应为
channel
now。它只有一个字符,编辑必须更改至少6个字符,所以我必须找到其他东西来挑剔。。。最好自己解决:)还要注意,每个潜在客户只能有一个相关频道。因此,设置
channel=channel\u序列化程序(many=True,…)
没有意义-这里不能有很多通道。正如所提供的答案所表明的那样,把它变成查尔菲尔德是一个更好的主意。