Отображение полей таблицы x в GET-запросе таблицы y, имеющей внешний ключ таблицы x (Django)

Мне нужна помощь, пожалуйста, я застрял на этом на некоторое время.

У меня есть две таблицы, Share и Fund.

Share.py

class Share(models.Model):
ShareName = models.CharField(max_length=100, unique=True, default="N/A")
ISINCode = models.CharField(max_length=100, primary_key=True, default="N/A")

Fund.py

class Fund(models.Model):
    FundID = models.AutoField(primary_key=True)
    FundName = models.CharField(max_length=100, default="N/A", unique=True)
    FundIdentifier = models.CharField(max_length=100, default="N/A")
    PercentOfFundNetAssets = models.DecimalField(decimal_places=2, max_digits=5, default=0.00)
    ISINCode = models.ForeignKey(Share, to_field='ISINCode', related_name="toshares",
                                 on_delete=models.CASCADE)

    class Meta: 
    unique_together = ('FundIdentifier', 'ISINCode')

По отдельности они не представляли проблемы для GET/POST/PUT и т.д. Однако теперь важно, чтобы при GET-запросах получалась таблица фондов, а также соответствующие поля акций, которые относятся к каждой строке фонда. Смотрите ниже:

Как теперь выглядит JSON фонда при GET-запросе

[
    {
        "FundName": "Some fund",
        "FundIdentifier": "FND001",
        "PercentOfFundNetAssets": "3.82",
        "ISINCode": "SHR001"
    },
]

Как я хочу, чтобы JSON фонда выглядел при GET запросе

[
  {
    "FundName": "Some fund",
    "FundIdentifier": "FND001",
    "PercentOfFundNetAssets": 3.82,
    "ISINCode": "SHR001",
    "share": [
      {
        "ISINCode": "SHR001",
        "ShareName": "Some share"
      }
    ]
  }
]

Я бы также согласился на что-то вроде этого.

[
  {
    "FundName": "Some fund",
    "FundIdentifier": "FND001",
    "PercentOfFundNetAssets": 3.82,
    "ISINCode": "SHR001",
    "ISINCode": "SHR001",
    "ShareName": "Some share"
  }
]

В любом случае, каждый объект fund json будет иметь только один объект share внутри с соответствующими полями в каждой строке, как показано ниже. Кажется достаточно простым... но я продолжаю сталкиваться с проблемами, поэтому буду благодарен, если кто-нибудь укажет, где я ошибаюсь.

ShareSerializer.py

class ShareSerializer(serializers.ModelSerializer):
class Meta:
    model = Share
    fields = ('ShareName', 'ISINCode')

def get_serializer(self, *args, **kwargs):
    if "data" in kwargs:
        data = kwargs["data"]

        # check if many is required
        if isinstance(data, list):
            kwargs["many"] = True

    return super(ShareViewSet, self).get_serializer(*args, **kwargs)

FundSerializer.py

class FundSerializer(serializers.ModelSerializer):
    toshares = ShareSerializer(many=True, read_only=True)

    class Meta:
        model = Fund
        fields = ('FundName', 'FundIdentifier', 'PercentOfFundNetAssets', 'ISINCode', 'toshares')

ShareViewSet.py

class ShareViewSet(ModelViewSet):
    authentication_classes = []
    permission_classes = []
    queryset = Share.objects.all().order_by('ISINCode')
    serializer_class = ShareSerializer
    paginator = None

    def get_serializer(self, *args, **kwargs):
        if "data" in kwargs:
            data = kwargs["data"]

            # check if many is required
            if isinstance(data, list):
                kwargs["many"] = True

        return super(ShareViewSet, self).get_serializer(*args, **kwargs)

FundViewSet.py

class FundViewSet(ModelViewSet):
    authentication_classes = []
    permission_classes = []

    queryset = Fund.objects.all().order_by('FundIdentifier')
    serializer_class = FundSerializer
    paginator = None

        def get_serializer(self, *args, **kwargs):
        if "data" in kwargs:
            data = kwargs["data"]

            # check if many is required
            if isinstance(data, list):
                kwargs["many"] = True

        return super(FundViewSet, self).get_serializer(*args, **kwargs)

Вот запрос PostgreSQL, который достигает того, что я хочу, но я не смог эмулировать в Django:

SELECT * FROM fund f 
INNER JOIN share s ON s."ISINCode" = f."ISINCode_id" 
ORDER BY "FundID" ASC

Что я пробовал:

  • Я пробовал использовать select_related в queryset в fund viewset (см. ниже):

    queryset = Fund.objects.select_related('ISINCode').all().order_by('FundIdentifier') для Fund в queryset: print(Fund.ISINCode)

    .

Я могу получить доступ к полям таблицы share таким образом (ну, по крайней мере, вывести их на консоль), но я не знаю, как использовать это для добавления их в queryset, чтобы я мог получить эти столбцы/данные в GET-запросе.

  • related_name/set_share (пробовал оба варианта, но опции related_name или set_share в queryset не распознаются по какой-то причине...)
  • raw sql (manager.raw и cursor, первый не работает для объединения таблиц, но работает в других случаях, cursor работает, но я не знаю, как перевести cursor.fetchall() в формат queryset). Также это не идеальное решение в любом случае, судя по комментариям/документации.
  • Пробовал добавлять фильтр к queryset и ссылаться на share__ShareName или какое-то поле
  • .
  • Узнал о python shell, где были сделаны некоторые примеры этого (но я использую Postman, фронтенд или PGAdmin для проверки своей работы вместо этого), поэтому предпочел бы не использовать это, если это может дать решение каким-то образом
  • .
  • Я также видел упоминания о файле шаблона и использовании html для достижения того, что я хочу, но я бы предпочел не искать возможности сделать что-то подобное
  • .

Все еще очень много новичков в Django, поэтому я уверен, что одна из вещей, которые я пробовал выше, была просто моей неправильной работой и отсутствием некоторых основ Django. Буду признателен за любую помощь... чем проще решение, тем лучше.

Спасибо!

Проблема, с которой я сталкивался все это время, заключалась в том, что я не включил глубину в мета-часть сериализатора фонда.

Изменение

class Meta:
    model = Fund
    fields = ('FundName', 'FundIdentifier', 'PercentOfFundNetAssets', 'ISINCode', 'toshares')

to

class Meta:
    model = Fund
    fields = ('FundName', 'FundIdentifier', 'PercentOfFundNetAssets', 'ISINCode', 'toshares')
    depth = 1

исправил мою проблему. Набор запросов по умолчанию, который я использовал, работает нормально после внесения этого изменения.

Запрос Get теперь посылается примерно так.

[
  {
    "FundName": "Some fund",
    "FundIdentifier": "FND001",
    "PercentOfFundNetAssets": 3.82,
    "ISINCode": {
        "ISINCode": "SHR001",
        "ShareName": "Some share"
      }   
  }
]
Вернуться на верх