Джанго все связанные данные - PullRequest
0 голосов
/ 10 октября 2019
class Docs(models.Model):
    doc_id = models.BigIntegerField(primary_key=True)
    journal = models.CharField(max_length=50, blank=True, null=True)
    year = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'docs'

class Assays(models.Model):
    assay_id = models.BigIntegerField(primary_key=True)
    doc = models.ForeignKey('Docs', models.DO_NOTHING)
    description = models.CharField(max_length=4000, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'assays'

class Activities(models.Model):
    activity_id = models.BigIntegerField(primary_key=True)
    assay = models.ForeignKey(Assays, models.DO_NOTHING)
    doc = models.ForeignKey(Docs, models.DO_NOTHING, blank=True, null=True)
    record = models.ForeignKey('CompoundRecords', models.DO_NOTHING)

    class Meta:
    managed = False
    db_table = 'activities'

Я заранее прошу прощения, если этот ответ легко найти в другом месте. Я провел поиск по всему и не вижу простого способа запрашивать мои данные настолько интуитивно, насколько мне кажется, это возможно.

Это классы для 3 таблиц. Фактический набор данных ближе к 100 таблицам. Каждый doc_id может иметь один или несколько связанных Activity_ID. Каждый идентификатор действия связан с одним идентификатором assay_id.

Моя цель - получить все связанные данные для каждого действия в одном документе. Например:

query_activities_values = Docs.objects.get(doc_id=5535).activities_set.values()
for y in query_activities_values:
    print(y)
    break
>>> {'activity_id': 753688, 'assay_id': 158542, 'doc_id': 5535, .....

Возвращает 32 словаря (показана только часть первого) для столбцов в таблице «Деятельности» с doc_id = 5535. Я хотел бы сделать еще один шаг, а также автоматически извлекать все данные из таблицы Assays, связанной с соответствующим assay_id для каждого словаря.

Я могу получить доступ к данным Assay через аналогичный запрос, но только с явным указанием каждого поля:

query_activities_values = Docs.objects.get(doc_id=5535).activities_set.values('assay', 'assay__assay_type', 'assay__description')
for y in query_activities_values:
    print(y)
    break

Я хотел бы один запрос, который находит не только данные анализа и связанные данные анализадля одного Activity_id, но находит все данные и связанные данные для 90+ других таблиц, связанных в модели

Спасибо

Обновление 1

IЯ нашел этот код, который работает на удивление хорошо для моих нужд, однако мне было любопытно, если это лучший метод:

from django.forms.models import model_to_dict def serial_model(modelobj): opts = modelobj._meta.fields modeldict = model_to_dict(modelobj) for m in opts: if m.is_relation: foreignkey = getattr(modelobj, m.name) if foreignkey: try: modeldict[m.name] = serial_model(foreignkey) except: pass return modeldict

Это не слишком много кода, но я подумал, что можетбыть более встроенным способом сделать это.

1 Ответ

0 голосов
/ 10 октября 2019

Что вам нужно, это prefetch_related:

Django 2.2 Документы, связанные с предварительной выборкой

query_activities_values = Docs.objects.get(doc_id=5535).activities_set.values()

Стали бы:

query_activities_values = Docs.objects.prefetch_related(models.Prefetch("activities_set", to_attr="activities"), models.Prefetch("assays_set", to_attr="assays")).get(doc_id=5535)

Новые атрибутыбудут созданы под названием «действия» и «анализы», которые вы можете использовать для извлечения данных.

Еще одна вещь. На самом деле это не 1 запрос. Это 3. Однако, если вы получаете больше чем один объект из Документов, он все равно будет 3.

Кроме того, есть ли причина, по которой вы используете BigIntegerField?

...