Django: Dizeden model alınsın mı?


133

Django'da, aşağıdaki gibi ilişkiler belirleyebilirsiniz:

author = ForeignKey('Person')

Ve sonra dahili olarak "Kişi" dizesini modele dönüştürmesi gerekir Person.

Bunu yapan işlev nerede? Kullanmak istiyorum ama bulamıyorum.

Yanıtlar:


167

Django 3.0 itibariyle, AppConfig.get_model(model_name, require_ready=True)

Django 1.9'dan itibaren yöntem django.apps.AppConfig.get_model(model_name).
- danihp

Django 1.7'den itibaren django.db.models.loading, kullanımdan kaldırıldı (1.9'da kaldırılacak), yeni uygulama yükleme sistemi lehine.
- Scott Woodall


Buldum. Burada tanımlanmıştır:

from django.db.models.loading import get_model

Şu şekilde tanımlanır:

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

11
Bu çözüm Django 1.7'de kullanımdan kaldırılmıştır, çözüm için bu diğer yanıta bakın: stackoverflow.com/a/26126935/155987
Tim Saylor

4
Merhaba @mpen, cevabınızı güncellemenizi öneririm. Django 1.9'da get_model AppConfig üzerinde tanımlanmıştır :from django.apps import AppConfig
dani herrera

1
django.apps.AppConfig, model nesnesi gibi çalışamayan bir jeneratör türüdür.
Neeraj Kumar

2
Django 1.7+ sürümünde, üzerinden ulaşılabilen Django uygulama kayıt defterinde get_model () kullanmak daha iyidir django.apps.apps.get_model(model_name). AppConfig nesneleri farklı bir amaca yöneliktir ve çağırmak için bir AppConfig örneği oluşturmanızı gerektirir get_model().
zlovelady

2
Django 1.11'in @luke_aus tarafından sağlanan yanıta ihtiyacı var
Georg Zimmer

132

django.db.models.loadingedildi Django'ya 1.7'de kaldırıldı ( 1.9 uzaklaştırıldı yeni lehine) uygulama yükleme sistemi .

Django 1.7 belgeleri bunun yerine bize şunu verir:

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

Eskiden pydoc'un "locate" işlevini kullanırdım ... buradaki farktan emin değilim, ancak Django içinde kalmak için bu yönteme geçtim. Teşekkürler.
warath-coder

61

sadece takılıp kalan herkes için (benim yaptığım gibi):

from django.apps import apps

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

app_nameolması gerektiği gibi tırnak işaretleri kullanılarak listelenmelidir model_name(yani içe aktarmaya çalışmayın)

get_model küçük veya büyük 'model_name' kabul eder


32

Çoğu model "dizesi" "appname.modelname" biçiminde görünür, bu nedenle get_model'de bu varyasyonu kullanmak isteyebilirsiniz.

from django.db.models.loading import get_model

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

Genellikle bir model haline tür dizeleri döner Django kod parçası biraz daha Bu kompleks dan 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)

Bana göre, bunu çekirdek kodda tek bir işleve bölmek için bu iyi bir durum gibi görünüyor. Ancak, dizelerinizin "Uygulama Modeli" biçiminde olduğunu biliyorsanız, yukarıdaki iki satır çalışacaktır.


3
Ben 2 satır olması gerektiğini düşünüyorum: your_model = get_model(*your_string.rsplit('.', 1)). Uygulama etiketi bazen noktalı biçimdedir, ancak model adı her zaman geçerli bir tanımlayıcıdır.
Rockallite

1
Görünüşe göre yenide bu gerekli değil apps.get_model. "Kısayol olarak, bu yöntem aynı zamanda formdaki tek bir argümanı da kabul eder app_label.model_name."
Ryne Everett

16

Bunu Django 1.7+ ile yapmanın kutsanmış yolu şudur:

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

Bu nedenle, tüm çerçeve eğitimlerinin kanonik örneğinde:

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

9

Modelinizin hangi uygulamada bulunduğunu bilmiyorsanız, şu şekilde arama yapabilirsiniz:

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

Your_model_name'in küçük harf olması gerektiğini unutmayın.


4

Django'da nerede yapıldığından emin değilim, ama bunu yapabilirsin.

Yansıma yoluyla sınıf adını dizeye eşleme.

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

1
Clls .__ sınıf __.__ name__ mi yoksa sadece clls .__ name__ mı?
Vinayak Kaniyarakkal

4

Tembeller için daha az kod içeren başka bir yorum. Django 2+ ile test edildi

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

1

Dizeden bir sınıf elde etmek için django'ya daha az özgü bir yaklaşım:

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

ya da importlib'i burada gösterildiği gibi kullanabilirsiniz :

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.