web-dev-qa-db-fra.com

Django: Obtenir le modèle de la chaîne?

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.

118
mpen

À 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):
157
mpen

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'>
121
Scott Woodall

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'

48
lukeaus

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.

33
Ch'marr

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
15
Craig Labenz

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.

9
Ola Nguyen Van

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
3
jbcurtin

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')
1
Schubisu