W Django możesz określić relacje takie jak:
author = ForeignKey('Person')
Następnie wewnętrznie musi przekształcić łańcuch „Osoba” w model Person
.
Gdzie jest funkcja, która to robi? Chcę go użyć, ale nie mogę go znaleźć.
Odpowiedzi:
Od Django 3.0 to
AppConfig.get_model(model_name, require_ready=True)
Od wersji Django 1.9 metoda to
django.apps.AppConfig.get_model(model_name)
.
- danihp
Począwszy od Django 1.7,
django.db.models.loading
jest on przestarzały (ma zostać usunięty w 1.9) na rzecz nowego systemu ładowania aplikacji.
- Scott Woodall
Znalazłem to. Jest zdefiniowane tutaj:
from django.db.models.loading import get_model
Zdefiniowana jako:
def get_model(self, app_label, model_name, seed_cache=True):
from django.apps import AppConfig
django.apps.apps.get_model(model_name)
. Obiekty AppConfig są przeznaczone do innego celu i wymagają utworzenia wystąpienia AppConfig w celu wywołania get_model()
.
django.db.models.loading
został przestarzały w Django 1.7 ( usunięty w 1.9 ) na rzecz nowego systemu ładowania aplikacji .
Zamiast tego dokumentacja Django 1.7 zawiera następujące informacje:
>>> from django.apps import apps
>>> User = apps.get_model(app_label='auth', model_name='User')
>>> print(User)
<class 'django.contrib.auth.models.User'>
Większość „ciągów” modelu ma postać „nazwa_aplikacji.modelname”, więc możesz chcieć użyć tej odmiany w get_model
from django.db.models.loading import get_model
your_model = get_model ( *your_string.split('.',1) )
Część kodu django, która zwykle zamienia takie łańcuchy w model, jest trochę bardziej złożona 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)
Wydaje mi się, że jest to dobry przypadek do podzielenia tego na jedną funkcję w kodzie podstawowym. Jeśli jednak wiesz, że Twoje ciągi znaków są w formacie „App.Model”, powyższe dwie linijki będą działać.
your_model = get_model(*your_string.rsplit('.', 1))
. Etykieta aplikacji ma czasem format kropkowy, jednak nazwa modelu jest zawsze prawidłowym identyfikatorem.
apps.get_model
. „W skrócie ta metoda akceptuje również pojedynczy argument w formularzu app_label.model_name
”.
Błogosławionym sposobem na to w Django 1.7+ jest:
import django
model_cls = django.apps.apps.get_model('app_name', 'model_name')
Tak więc w kanonicznym przykładzie wszystkich samouczków dotyczących frameworka:
import django
entry_cls = django.apps.apps.get_model('blog', 'entry') # Case insensitive
Jeśli nie wiesz, w której aplikacji istnieje Twój model, możesz przeszukać go w ten sposób:
from django.contrib.contenttypes.models import ContentType
ct = ContentType.objects.get(model='your_model_name')
model = ct.model_class()
Pamiętaj, że twoja_nazwa_modelu musi być zapisana małymi literami.
Nie jestem pewien, gdzie to się robi w Django, ale możesz to zrobić.
Mapowanie nazwy klasy na ciąg za pomocą odbicia.
classes = [Person,Child,Parent]
def find_class(name):
for clls in classes:
if clls.__class__.__name__ == name:
return clls
Rozwiązanie 2020:
from django.apps import apps
apps.get_model('app_name', 'Model')
na twój np .:
apps.get_model('people', 'Person')
Oto podejście mniej specyficzne dla django, aby pobrać klasę z łańcucha:
mymodels = ['ModelA', 'ModelB']
model_list = __import__('<appname>.models', fromlist=mymodels)
model_a = getattr(model_list, 'ModelA')
lub możesz użyć importlib, jak pokazano tutaj :
import importlib
myapp_models = importlib.import_module('<appname>.models')
model_a = getattr(myapp_models, 'ModelA')