如何从与foriegn键链接的表中获取逗号分隔的值?

时间:2019-04-12 07:24:21

标签: django django-rest-framework

我有一个问题想要在响应中返回图像列表。 我创建了一个名为pest_id的外键,该外键链接到主知识库表。现在,如果我使用指定的方式,例如

KnowledgeBase.objects.values('id', 'pest_id', 'pest__name', 
'pest__title', 'pestimages__image', 'front_image', 'cause', 
'effect', 'remedy', 'prevention')

我得到了列表,但输出是

{
        "id": 1473,
        "pest_id": 249,
        "pest__name": "Worker stuff little store three operation news. Move world affect small. Entire past face partner.",
        "pest__title": "surya",
        "pestimages__image": "extras/f4e8482c69e4e562d86149b45da8565e.jpg",
        "front_image": "images/plant-3250.jpg",
        "cause": "Summer popular music provide white.",
        "effect": "That unit article practice feel nature.",
        "remedy": "Car including hair before impact least scene tough. Generation job painting in develop issue mean half.",
        "prevention": "Every business price step themselves own. Treatment guess far senior response. See a development last."
    },
    {
        "id": 1473,
        "pest_id": 249,
        "pest__name": "Worker stuff little store three operation news. Move world affect small. Entire past face partner.",
        "pest__title": "surya",
        "pestimages__image": "extras/f2f05d15bf695d5bb45ca909887230f9.jpg",
        "front_image": "images/plant-3250.jpg",
        "cause": "Summer popular music provide white.",
        "effect": "That unit article practice feel nature.",
        "remedy": "Car including hair before impact least scene tough. Generation job painting in develop issue mean half.",
        "prevention": "Every business price step themselves own. Treatment guess far senior response. See a development last."
    },

但是预期的输出是:

{
        "pest_id": 249,
        "id": 1473,
        "pest__name": "Worker stuff little store three operation news. Move world affect small. Entire past face partner.",
        "pest__title": "surya",
        "images": [
            "extras/f4e8482c69e4e562d86149b45da8565e.jpg",
            "extras/f2f05d15bf695d5bb45ca909887230f9.jpg",
            "extras/ea1a1b02e734d1130c80e45880c106d3.jpg",
            "extras/e66b165e767d45ac2ef046873a27ed29.jpg",
            "extras/e54ed50db3e1079db9284bd30494de76.jpg",
            "extras/de37d314715709b183d88ec82184330a.jpg",
            "extras/dac29948d89054e2ede1b957b53d3ec6.jpg",
            "extras/d7750c85b3e5d0b3cb7adaffa5474a11.jpg",
            "extras/d468a3e96a0a7249a32e614ab7a4d8fa.jpg"
        ],
        "front_image": "images/plant-3250.jpg",
        "cause": "Summer popular music provide white.",
        "effect": "That unit article practice feel nature.",
        "remedy": "Car including hair before impact least scene tough. Generation job painting in develop issue mean half.",
        "prevention": "Every business price step themselves own. Treatment guess far senior response. See a development last."
    },

因此,您可以看到整个结果被重复的次数与PestImages表具有外键pest_id的次数相同。

我真正想要的是它应该以逗号分隔的值返回pestimages__image字段。

我需要更改型号吗?

我曾尝试寻找解决问题的解决方案,但是却找不到任何提示。

最终,我不得不编写自己的方法,这需要大量时间来处理结果。

id_list = KnowledgeBase.objects.values_list('id')
    ResponseList = []
    for id in range(len(id_list)):
        kb = KnowledgeBase.objects.get(id=id_list[id][0])
        pests = Pest.objects.get(id=kb.pest_id)
        pestimg = [', '.join(map(str, x)) for x in PestImages.objects.filter(pest_id=id_list[id][0]).values_list('image')]
        ResponseList.append(
            {
                 'pest_id': kb.pest_id,
                 'id': id_list[id][0],
                 'pest__name': pests.name,
                 'pest__title': pests.title,
                 'images': pestimg,
                 'front_image': str(kb.front_image),
                 'cause': kb.cause,
                 'effect': kb.effect,
                 'remedy': kb.remedy,
                 'prevention': kb.prevention
            }
        )
    return Response(ResponseList, status=HTTP_200_OK)

现在,尽管此功能可以达到我的目的,但是与普通方法的26ms相比,它需要1700ms的响应时间。

我的模特是:

class KnowledgeBase(models.Model):
    pest = models.OneToOneField(Pest, on_delete=models.CASCADE)
    cause = models.TextField()
    front_image = models.ImageField(upload_to='images/', blank=False, null=False, default='images/plant-3250.jpg')
    effect = models.TextField()
    remedy = models.TextField()
    prevention = models.TextField()

class PestImages(models.Model):
    pest = models.ForeignKey('KnowledgeBase', on_delete=models.PROTECT)
    image = models.ImageField(upload_to='extras')

class Pest(models.Model):
    name = models.TextField()
    title = models.CharField(max_length=255, unique=True)

有什么办法可以解决这个问题?

时差巨大:

  

〜30ms具有正常功能,具有冗余信息   正常功能:KnowledgeBase.objects.values(*)

<30ms with normal function with redundant info

  

〜1700ms(使用我的功能/使用序列化)。

     

我的函数已发布在上方,答案中列出了序列化方法。

>1700ms with my function/using serialization

1 个答案:

答案 0 :(得分:1)

定义一个序列化器类

from rest_framework import serializers


class KnowledgeBaseSerializer(serializers.ModelSerializer):
    images = serializers.SerializerMethodField()
    pest__name = serializer.Charfield(source="pest.name")
    pest__title = serializer.Charfield(source="pest.title")

    def get_images(self, kb):
        return [str(item) for item in kb.pestimages__image.all()]

    class Meta:
        model = KnowledgeBase
        fields = ('id', 'pest_id', 'pest__name', 'pest__title', 'front_image', 'cause', 'effect', 'remedy', 'prevention', 'images')

然后

mydata = KnowledgeBaseSerializer(KnowledgeBase.objects.all(), many=True).data