Как динамически получить класс модели Django?

Не имея полного пути к модулю модели Django, возможно ли сделать что-то вроде:

model = 'User' [in Django namespace]
model.objects.all()

... в отличие от:

User.objects.all().

Обновлено: я пытаюсь сделать этот вызов на основе ввода командной строки. Можно ли избежать оператора импорта, например,

model = django.authx.models.User

Без Django, возвращающего ошибку:

"global name django is not defined."
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
33
0
14 665
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

from django.authx.models import User
model = User
model.objects.all()

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

modelname = "User"
model = globals()[modelname]

Но возиться с globals () может быть немного опасно в некоторых контекстах. Так что обращайтесь осторожно :)

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

SapphireSun 01.01.2010 00:51
Ответ принят как подходящий

Я думаю, вы ищете это:

from django.db.models.loading import get_model
model = get_model('app_name', 'model_name')

Конечно, есть и другие методы, но я бы так поступил, если вы не знаете, какой файл моделей нужно импортировать в свое пространство имен. (Обратите внимание, что на самом деле нет способа безопасно получить модель, не зная заранее, к какому приложению она принадлежит. Посмотрите исходный код load.py, если вы хотите проверить свою удачу при итерации по всем моделям приложений.)

Обновление для Django 1.7+: Согласно Django график прекращения поддержки, django.db.models.loading устарел в Django 1.7 и будет удален в Django 1.9. Как указано в Ответ Аласдэра, В Django 1.7+ есть реестр приложений. Вы можете использовать метод apps.get_model для динамического получения модели:

from django.apps import apps
MyModel = apps.get_model('app_label', 'MyModel')

Оглядываясь назад, я думаю, что он тоже этого ищет.

cdleary 05.01.2009 02:46

Все это полезные ответы (мою проблему можно решить разными способами), но этот наиболее прямо касается того, что я ищу.

thebossman 05.01.2009 06:50

model = django.authx.models.User

? Django returns an error, "global name django is not defined."

Django не возвращает ошибку. Python делает.

Во-первых, вы ДОЛЖНЫ импортировать модель. Вы должны импортировать его с помощью

from django.authx.models import User

Во-вторых, если вы получаете сообщение о том, что django не определен, значит, Django установлен неправильно. У вас должен быть Django на вашем PYTHONPATH или установлен в Python lib / site-packages.

Чтобы правильно установить Django, см. http://docs.djangoproject.com/en/dev/intro/install/#intro-install

Классы в Python являются объектами «первого класса», то есть ими можно передавать и манипулировать ими, как и всеми другими объектами.

Модели - это классы - это видно по тому факту, что вы создаете новые модели с помощью операторов класса:

class Person(models.Model):
    last_name = models.CharField(max_length=64)

class AnthropomorphicBear(models.Model):
    last_name = models.CharField(max_length=64)

Идентификаторы Person и AnthropomorphicBear привязаны к классам Django, поэтому вы можете передавать их. Это может быть полезно, если вы хотите создать вспомогательные функции, которые работают на уровне модели (и имеют общий интерфейс):

def print_obj_by_last_name(model, last_name):
    model_name = model.__name__
    matches = model.objects.filter(last_name=last_name).all()
    print('{0}: {1!r}'.format(model_name, matches))

Таким образом, print_obj_by_last_name будет работать как с моделями Person, так и с AnthropomorphicBear. Просто передайте модель так:

print_obj_by_last_name(model=Person, last_name='Dole')
print_obj_by_last_name(model=AnthropomorphicBear, last_name='Fozzy')

Для Django 1.7+ существует реестр приложений. Вы можете использовать метод apps.get_model для динамического получения модели.

from django.apps import apps
MyModel = apps.get_model('app_label', 'MyModel')

Теперь, когда django.db.models.loading был устарело в Django 1.9, это, вероятно, лучший подход для динамической загрузки модели в Django.

Mike Covington 16.09.2015 11:54

К сожалению, django.db.models.loading устарел в версии 1.7 и был удален в версии 1.9. Спасибо @Alasdair за разъяснение этого при редактировании принятый ответ.

Mike Covington 16.09.2015 12:16

Спасательное решение для коллизий круговых ссылок.

helvete 13.04.2017 16:42

Это должен быть принятый ответ, поскольку django.db.models.loading устарел в Django 1.9: github.com/django/django/blob/…

Blairg23 06.05.2019 23:09

Другие вопросы по теме