Django: укажите все обратные отношения модели

Я бы хотел, чтобы мое приложение django служило списку любых полей модели (это поможет самому сборщику GUI).

Представьте себе классы (игнорируйте тот факт, что все поле Steps может быть в Item, у меня есть мои причины:-))

class Item(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()

class Steps(models.Model):
    item = models.OneToOneField('Item', related_name='steps')
    design = models.BooleanField(default=False)
    prototype = models.BooleanField(default=False)
    production = models.BooleanField(default=False)

Теперь, когда я хочу перечислить поля модели:

def get_fields(model):
    return model._meta.fields + model._meta.many_to_many

Но я также хотел бы получить список "связанных" друг с другом внешних ключей с моими моделями. В моем случае Item.steps не будет в этом списке.

Я обнаружил, что model._meta.get_all_field_names содержит все связанные поля.

Но когда я вызываю Item._meta.get_field_by_name('steps'), он возвращает кортеж, содержащий RelatedObject, который сразу не сообщает мне, является ли это одним отношением или "один ко многим" (я хочу перечислить только отмененные одноразовые слова, одно отношение).

Кроме того, я могу использовать этот бит кода:

from django.db.models.fields.related import SingleRelatedObjectDescriptor
reversed_f_keys = [attr for attr in Item.__dict__.values() \
                  if isinstance(attr, SingleRelatedObjectDescriptor)]

Но я не очень доволен этим.

Любая помощь, идея, советы приветствуются!

Приветствия

Ответ 1

Это было изменено (в 1.8, я думаю), и ответ Оливье больше не работает. Согласно docs, новый способ -

[f for f in User._meta.get_fields()
    if f.auto_created and not f.concrete]

Это включает в себя один к одному, много-к-одному и многие-ко-многим.

Ответ 2

Я узнал, что есть методы Model._meta, которые могут дать мне то, что я хочу.

my_model = get_model('app_name','model_name')
# Reverse foreign key relations
reverse_fks = my_model._meta.get_all_related_objects()
# Reverse M2M relations
reverse_m2ms = my_model._meta.get_all_related_many_to_many_objects()

Разбирая содержимое отношений, я могу догадаться, было ли "прямое" поле OneToOneField или что-то еще.

Ответ 3

А как насчет этого:

oneToOneFieldNames = [
    field_name 
    for field_name in Item._meta.get_all_field_names() 
    if isinstance(
        getattr(
            Item._meta.get_field_by_name(field_name)[0], 
            'field', 
            None
        ), 
        models.OneToOneField
    )
]

Связанный объект может иметь атрибут Field для отношений. Вам просто нужно проверить, является ли это поле OneToOne, и вы можете получить только то, что хотите.