Как получить значения, разделенные запятыми, из таблицы, связанной с ключом foriegn?

#django #django-rest-framework

#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)
  

Теперь, хотя эта функция служит моей цели, но для ответа требуется 1700 мс по сравнению с 26 мс обычного метода.

Мои модели:

 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)
  

Есть ли какой-нибудь способ это исправить?

Разница во времени огромна:

~ 30 мс с нормальной функцией с избыточной информацией Нормальная функция: база знаний.объекты.значения (*)

<30 мс с нормальной функцией с избыточной информацией

~ 1700 мс с моей функцией / с использованием сериализации..

Моя функция опубликована выше, а метод сериализации указан в ответе.

> 1700 мс с моей функцией / с использованием сериализации

Комментарии:

1. Пожалуйста, прокомментируйте, если кому-то нужна дополнительная информация, я добавлю пункты в вопросе.

2. Можете ли вы опубликовать свои модели?

3. Да, конечно, я добавлю их в вопрос.

4. Я обновил свой вопрос.

5. @JPG вы удалили свой ответ? Сериализация — это путь вперед для меня. Я проверю это.

Ответ №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
  

Комментарии:

1. django.core.exceptions. Неправильно сконфигурировано: имя поля pest__name недопустимо для модели KnowledgeBase . Возникает ошибка

2. После исправления двух строк, pest__name = serializers . CharField(источник =»pest.name «) pest__title = сериализаторы. CharField(источник =»pest.title») Я получаю, AttributeError: объект «База знаний» не имеет атрибута «pestimages__image»

3. И использование сериализатора не сокращает время. Пожалуйста, проверьте загруженные изображения в вопросе.

4. Почему мое редактирование было отклонено? В ответе синтаксическая ошибка.