Как получить доступ к данным модели через две промежуточные модели? - PullRequest
0 голосов
/ 28 октября 2019

Существует четыре модели:

class ObjectDataAdditional(models.Model):
    #various fields and:
    normal = models.ForeignKey(
        'ObjectDataNormalized',
        on_delete=models.CASCADE,
        null=True,
        related_name='additional_normal'
    )

class ObjectDataNormalized(models.Model):
    #various fields

class LinkedData(models.Model):
    many = models.ManyToManyField(
        ObjectDataNormalized,
        related_name='many_related',
    )

    def __str__(self):
        return u', '.join([str(a.pk) for a in self.many.all()])


class LinkedInfo(models.Model):
    linked_data = models.ForeignKey(
        LinkedData,
        on_delete=models.CASCADE,
        related_name='linked_data_related'
    )
    normalized = models.ForeignKey(
        ObjectDataNormalized,
        on_delete=models.CASCADE,
        related_name='normalized_related'
    )
    main = models.BooleanField(
        default=False,
        null=False,
    )

Здесь я получаю нужные мне данные:

info = LinkedInfo.objects.all().order_by('linked_data_id',
                                         '-main').select_related(
    'linked_data',
    'normalized',
).prefetch_related(
    'normalized__normal_object',
    'normalized__additional_normal'
).annotate(max_percentage=Max(
    'normalized__normal_object__additional_object__percentage_technical_readiness'))

final_data = []
temp_data = []
if info:
    last_link_pk = info[0].linked_data.pk
    for i, x in enumerate(info):
        if x.linked_data.pk == last_link_pk:
            temp_data.extend(create_temp_array(x, x.normalized.additional_normal))
            last_link_pk = x.linked_data.pk
        else:
            final_data.append(temp_data)
            temp_data = []
            temp_data.extend(create_temp_array(x))
            last_link_pk = x.linked_data.pk
        if info.count() - 1 == i:
            final_data.append(temp_data)
return Response(final_data)

Создание иерархии объектов по значению поля main в модели LinkedInfo:

def create_temp_array(data, additional_result=None):
    additional = data.normalized.additional_normal.filter(normal=data.normalized.pk).values()   
    result = [{
        'linked_data_id': data.linked_data.pk,
        'is_main': data.main,
        'normalized_object_id': data.normalized.pk,
        'name_data': data.normalized.name_data,
        'year_data': data.normalized.year_data.year,
        'build_code': data.normalized.build_code,
        'ministry_code': data.normalized.ministry_code,
        'territory_code': data.normalized.territory_code,
        'fcp': data.normalized.program_code,
        'max_percentage_technical_readiness': data.max_percentage,
        'additional': additional
    }]

    return result

data.normalized.additional_normal.filter(normal=data.normalized.pk).values() выполняет каждый вызов метода create_temp_array() (как и должно быть), но я просто не могу найти другой способ поместить данные из Additional_object в созданный массив.

Каждыйобъект ObjectDataNormalized может иметь несколько объектов ObjectDataAdditional их соединение установлено в модели ObjectDataAdditional в поле normal.

Я попытался создать промежуточную таблицу с двумя ForeignKey и добавить поле ManyToMany введите ObjectDataNormalized модель, на которую ссылается ObjectDataAdditional. Но всегда есть некоторые проблемы. Сейчас, насколько я вижу, я могу создать JSON, в котором я нуждаюсь, но этот способ чрезвычайно плох, потому что он не совсем оптимален, каждый раз, когда создается новый объект, также появляется новый запрос к БД.

Когда я повторяю (для цикла) x.normalized.additional_normal Я получаю

Объект «RelatedManager» не повторяется

, если я делаю это x.normalized.additional_normal:

build_analyzer.ObjectDataAdditional.None

Я пробовал много разных способов получить данные из ObjectDataAdditional, но он всегда отвечает мне ошибками.

...