Django:文字列からモデルを取得しますか?


133

Djangoでは、次のような関係を指定できます。

author = ForeignKey('Person')

そして、内部的には文字列 "Person"をモデルに変換する必要がありますPerson

これを行う関数はどこにありますか?使いたいのですが見つかりません。

回答:


167

Django 3.0以降では、 AppConfig.get_model(model_name, require_ready=True)

Django 1.9以降、メソッドはdjango.apps.AppConfig.get_model(model_name)です。
- ダニップ

Django 1.7以降django.db.models.loadingでは、新しいアプリケーションの読み込みシステムのために非推奨になりました(1.9で削除予定)。
- スコット・ウッドオール


それを見つけた。ここで定義されています:

from django.db.models.loading import get_model

として定義:

def get_model(self, app_label, model_name, seed_cache=True):

11
このソリューションはDjango 1.7で非推奨になりました。このソリューションの別の回答をご覧ください:stackoverflow.com/a/26126935/155987
Tim Saylor

4
こんにちは、@ mpen。回答を更新することをお勧めします。django 1.9では、get_modelはAppConfigで定義されています:from django.apps import AppConfig
dani herrera

1
django.apps.AppConfigは、モデルオブジェクトのように機能しないジェネレータタイプです。
Neeraj Kumar 2016

2
Django 1.7以降では、Djangoアプリレジストリでget_model()を使用することをお勧めしますdjango.apps.apps.get_model(model_name)。AppConfigオブジェクトは別の目的のためのものであり、を呼び出すためにAppConfigインスタンスを作成する必要がありますget_model()
zlovelady 2017年

2
Django 1.11には、@ luke_ausが提供する回答が必要です
Georg Zimmer

132

django.db.models.loadingジャンゴ1.7で非推奨1.9で削除、新規の賛成で)アプリケーションローディングシステム

Django 1.7のドキュメントでは、代わりに次のようになります。

>>> from django.apps import apps
>>> User = apps.get_model(app_label='auth', model_name='User')
>>> print(User)
<class 'django.contrib.auth.models.User'>

私はpydocの "locate"関数を使用していました...ここでの違いはわかりませんが、Django内に留まるために、私はこのメソッドに切り替えました。ありがとう。
warath-coder、2016

61

(私がしたように)行き詰まる人のために:

from django.apps import apps

model = apps.get_model('app_name', 'model_name')

app_name引用符を使用してリストする必要がありますmodel_name(つまり、インポートしないでください)。

get_model 小文字または大文字の「model_name」を受け入れます


32

ほとんどのモデル「文字列」は「appname.modelname」の形式で表示されるため、get_modelでこのバリエーションを使用することができます。

from django.db.models.loading import get_model

your_model = get_model ( *your_string.split('.',1) )

通常、そのような文字列をモデルに変換するdjangoコードの部分は、もう少し複雑django/db/models/fields/related.pyです。

    try:
        app_label, model_name = relation.split(".")
    except ValueError:
        # If we can't split, assume a model in current app
        app_label = cls._meta.app_label
        model_name = relation
    except AttributeError:
        # If it doesn't have a split it's actually a model class
        app_label = relation._meta.app_label
        model_name = relation._meta.object_name

# Try to look up the related model, and if it's already loaded resolve the
# string right away. If get_model returns None, it means that the related
# model isn't loaded yet, so we need to pend the relation until the class
# is prepared.
model = get_model(app_label, model_name,
                  seed_cache=False, only_installed=False)

私にとって、これはコアコードでこれを単一の関数に分割するための良いケースのようです。ただし、文字列が「App.Model」形式であることがわかっている場合は、上記の2つのライナーが機能します。


3
2行目は次のようになりますyour_model = get_model(*your_string.rsplit('.', 1))。アプリのラベルはドット形式の場合がありますが、モデル名は常に有効な識別子です。
Rockallite 2014年

1
新しいではこれは必要ないようapps.get_modelです。「ショートカットとして、このメソッドはフォームで単一の引数も受け入れますapp_label.model_name。」
Ryne Everett、

16

Django 1.7以降でこれを行うための祝福された方法は次のとおりです。

import django
model_cls = django.apps.apps.get_model('app_name', 'model_name')

したがって、すべてのフレームワークチュートリアルの標準的な例では、次のようになります。

import django
entry_cls = django.apps.apps.get_model('blog', 'entry')  # Case insensitive

9

モデルがどのアプリに存在するかわからない場合は、次の方法で検索できます。

from django.contrib.contenttypes.models import ContentType 
ct = ContentType.objects.get(model='your_model_name') 
model = ct.model_class()

your_model_nameは小文字でなければならないことに注意してください。


4

Djangoのどこで行われるかはわかりませんが、これは可能です。

リフレクションを介してクラス名を文字列にマッピングします。

classes = [Person,Child,Parent]
def find_class(name):
 for clls in classes:
  if clls.__class__.__name__ == name:
   return clls

1
それはclls .__ class __.__ name__または単なるclls .__ name__ですか?
Vinayak Kaniyarakkal

4

怠惰なコードが少ない別のレンディション。Django 2+でテスト済み

from django.apps import apps
model = apps.get_model("appname.ModelName") # e.g "accounts.User"

1

以下は、文字列からクラスを取得するための、それほどジャンゴ固有でないアプローチです:

mymodels = ['ModelA', 'ModelB']
model_list = __import__('<appname>.models', fromlist=mymodels)
model_a = getattr(model_list, 'ModelA')

または、ここに示すようにimportlibを使用できます。

import importlib
myapp_models = importlib.import_module('<appname>.models')
model_a = getattr(myapp_models, 'ModelA')

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.