Любой способ получить сквозные поля для объекта, связанного через поле Many2Many, не зная заранее имя столбца? - PullRequest
0 голосов
/ 11 сентября 2018

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

Так, например, если мои модели определены так (очень обобщенно):

class A(models.Model):
    somefieldA = models.TextField()
    m2mfield = models.ManyToManyField(B, through='AandB')

    def __unicode__(self):
        return self.somefieldA


class B(models.Model):
    somefieldB = models.TextField()

    def __unicode__(self):
        return self.somefieldB


class AandB(models.Model):
    a = models.ForeignKey(A)
    b = models.ForeignKey(B)
    field1 = models.DecimalField()
    field2 = models.TextField()
    field3 = models.DateField()

Теперь предположим, что у нас есть экземпляр объекта A a_obj.

Я могу получить все связанные объекты B, используя:

# This loop is there because I am working with other fields as well.
def instance_to_dict(instance):
    for field in instance._meta.get_fields():
        if field.many_to_many:
             m2m_mgr = getattr(instance, field.name)
             for idx, assoc_obj in enumerate(m2m_mgr.all()):
                 assoc_obj_str = str(assoc_obj)
                 # How to obtain the related through field values?
                 # m2m_mgr.through.objects.get() would need prior knowlegde
                 # of field name so get(a=instance, b=assoc_obj) is not possible
                 # m2m_mgr.through.objects.all() fetches all the objects
                 # in the Many to Many manager.

А затем позвоните instance_to_dict(a_obj). Этот метод может быть вызван путем передачи экземпляров других моделей. В идеале я хотел бы создать для obj и obj соответствующие поля для любого объекта. Возможно ли это сделать?

1 Ответ

0 голосов
/ 11 сентября 2018

В дополнение к явно определенному менеджеру ManyToMany существует также неявная обратная связь для ForeignKey от AandB до A.Таким образом, вы можете сделать что-то вроде этого:

for field in instance._meta.get_fields(include_hidden=True):
    if field.one_to_many:  # reverse ForeignKey
        m2m_through_mgr = getattr(instance, field.get_accessor_name())  # e.g. aandb_set
        m2m_through_mgr.all()  # all related instances from the through table

Другой подход состоит в том, чтобы просмотреть поля таблицы, глядя на field.related_model, чтобы увидеть, какой из них указывает на вашу исходную таблицу.

Все это становится довольно грязным, но мета-информации должно быть достаточно, чтобы делать то, что вы хотите.Одним из препятствий является то, что API не полностью задокументирован.В частности, поля отношений представлены экземплярами класса ManyToOneRel, который в Django 2.1 остается недокументированным по причинам, указанным в исходном коде .Поэтому я использую недокументированный метод get_accessor_name().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...