Dans Django, vous pouvez spécifier des relations telles que:
author = ForeignKey('Person')
Et en interne, il doit convertir la chaîne "Person" dans le modèle Person
.
Où est la fonction qui fait ça? Je veux l'utiliser, mais je ne le trouve pas.
À partir de Django 1.9, la méthode est
Django.apps.AppConfig.get_model(model_name)
.
- danihp
À partir de Django 1.7 le
Django.db.models.loading
est obsolète (à supprimer dans la version 1.9) au profit du nouveau système de chargement d'applications.
- Scott Woodall
Je l'ai trouvé C'est défini ici:
from Django.db.models.loading import get_model
Défini comme:
def get_model(self, app_label, model_name, seed_cache=True):
Django.db.models.loading
était obsolète dans Django 1.7 ( retiré de 1.9 ) en faveur du nouveau système de chargement d'application =.
Django 1.7 docs donnez-nous plutôt ceci:
>>> from Django.apps import apps
>>> User = apps.get_model(app_label='auth', model_name='User')
>>> print(User)
<class 'Django.contrib.auth.models.User'>
juste pour ceux qui sont coincés (comme je l'ai fait):
from Django.apps import apps
model = apps.get_model('app_name', 'model_name')
app_name
devrait être répertorié à l'aide de guillemets, de même que model_name
_ (c’est-à-dire, n’essayez pas de l’importer)
get_model
accepte les minuscules ou les majuscules 'nom_modèle'
La plupart des modèles de "chaînes" apparaissent sous la forme "appname.modelname", vous pouvez donc utiliser cette variante sur get_model.
from Django.db.models.loading import get_model
your_model = get_model ( *your_string.split('.',1) )
La partie du code Django qui convertit habituellement ces chaînes en modèle) est un peu plus complexe. Ceci de 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)
Pour moi, cela semble être un bon argument pour scinder cette tâche en une seule fonction dans le code principal. Toutefois, si vous savez que vos chaînes sont au format "App.Model", les deux doublures ci-dessus fonctionnent.
La manière bénie de faire cela en Django 1.7+ est:
import Django
model_cls = Django.apps.apps.get_model('app_name', 'model_name')
Donc, dans l'exemple canonique de tous les tutoriels sur le framework:
import Django
entry_cls = Django.apps.apps.get_model('blog', 'entry') # Case insensitive
Si vous ne savez pas dans quelle application votre modèle existe, vous pouvez le rechercher de la manière suivante:
from Django.contrib.contenttypes.models import ContentType
ct = ContentType.objects.get(model='your_model_name')
model = ct.model_class()
Rappelez-vous que votre_nom_modèle doit être en minuscule.
Je ne sais pas trop où cela se passe à Django, mais vous pouvez le faire.
Mapper le nom de la classe sur la chaîne par réflexion.
classes = [Person,Child,Parent]
def find_class(name):
for clls in classes:
if clls.__class__.__== name:
return clls
Voici une approche moins spécifique à Django pour obtenir une classe à partir de string:
mymodels = ['ModelA', 'ModelB']
model_list = __import__('<appname>.models', fromlist=mymodels)
model_a = getattr(model_list, 'ModelA')
ou vous pouvez utiliser importlib comme indiqué ici :
import importlib
myapp_models = importlib.import_module('<appname>.models')
model_a = getattr(myapp_models, 'ModelA')