Django : 문자열에서 모델을 가져 오시겠습니까?


133

장고에서는 다음과 같은 관계를 지정할 수 있습니다.

author = ForeignKey('Person')

그리고 내부적으로 문자열 "Person"을 모델로 변환해야합니다 Person.

이 기능을 수행하는 기능은 어디에 있습니까? 사용하고 싶지만 찾을 수 없습니다.

답변:


167

장고 3.0 기준으로 AppConfig.get_model(model_name, require_ready=True)

Django 1.9부터 방법은 django.apps.AppConfig.get_model(model_name)입니다.
- danihp

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

2
Django 1.7 이상에서는 Django 앱 레지스트리에서 get_model ()을 사용하는 것이 좋습니다 django.apps.apps.get_model(model_name). AppConfig 객체는 다른 용도로 사용되며을 호출하려면 AppConfig 인스턴스를 만들어야합니다 get_model().
zlovelady

2
Django 1.11은 @luke_aus
Georg Zimmer

132

django.db.models.loading장고 1.7에서 사용되지 않는 ( 1.9 제거 하여 새 찬성) 응용 프로그램 로딩 시스템 .

장고 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

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/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"형식 인 경우 위의 두 라이너가 작동합니다.


3
두 번째 줄은 다음과 같아야합니다 your_model = get_model(*your_string.rsplit('.', 1)). 앱 레이블은 점으로 표시되는 형식이지만 모델 이름은 항상 유효한 식별자입니다.
Rockallite

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

장고에서 어디에서했는지 확실하지 않지만이 작업을 수행 할 수 있습니다.

리플렉션을 통해 클래스 이름을 문자열에 매핑

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

게으른 코드가 적은 또 다른 표현. 장고 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.