Django: Récupère le modèle de la chaîne?

Dans Django, vous pouvez spécifier des relations comme:

author = ForeignKey('Person') 

Et puis en interne, il doit convertir la chaîne “Person” en la Person modèle.

Où est la fonction qui fait ça? Je veux l’utiliser, mais je ne le trouve pas.

A partir de Django 1.9, la méthode est django.apps.AppConfig.get_model(model_name) .
– danihp


Depuis Django 1.7, le django.db.models.loading est obsolète (à supprimer dans la version 1.9) en faveur du nouveau système de chargement des applications.
– Scott Woodall


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): 

Depuis Django 1.7, le django.db.models.loading est obsolète (à supprimer dans la version 1.9) en faveur du nouveau système de chargement des applications. Les 1.7 documents nous donnent à la place:

 $ python manage.py shell Python 2.7.6 (default, Mar 5 2014, 10:59:47) >>> from django.apps import apps >>> User = apps.get_model(app_label='auth', model_name='User') >>> print User  >>> 

Edité par tttthomasssss commentaire.

La plupart des “chaînes” de modèle apparaissent sous la forme “nomapplication.nomdémarrage”, vous pouvez donc utiliser cette variante sur get_model

 from django.db.models.loading import get_model your_model = get_model ( *your_ssortingng.split('.',1) ) 

La partie du code django qui transforme généralement de telles chaînes en un modèle est un peu plus complexe. Ceci à partir 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 AtsortingbuteError: # 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 # ssortingng 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 exemple pour diviser cela en une seule fonction dans le code principal. Cependant, si vous savez que vos chaînes sont au format “App.Model”, les deux lignes ci-dessus fonctionneront.

juste pour quiconque se coince (comme je l’ai fait):

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

app_name doit être répertorié en utilisant des guillemets, comme le devrait model_name (c’est-à-dire n’essayez pas de l’importer)

get_model accepte les minuscules ou les majuscules ‘model_name’

La manière bénie de le faire dans Django 1.7+ est la suivante:

 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.consortingb.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 suis pas sûr où cela est fait dans Django, mais vous pouvez le faire.

Mapper le nom de la classe à la chaîne via la reflection.

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

Voici une approche moins spécifique au django pour obtenir une classe à partir d’une chaîne:

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

ou vous pouvez utiliser importlib comme indiqué ici :

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