Comment récupérer dynamiquement une classe de modèle Django?

Sans avoir le chemin complet du module D'un modèle Django, est-il possible de faire quelque chose comme:

model = 'User' [in Django namespace]
model.objects.all()

... par opposition à:

User.objects.all().

EDIT: j'essaie de faire cet appel en fonction de l'entrée de ligne de commande. Est-il possible d'éviter l'instruction import, par exemple,

model = django.authx.models.User

Sans que Django renvoie l'erreur:

"global name django is not defined."
22
demandé sur Daniel Naab 2009-01-05 01:32:50

6 réponses

Je pense que vous cherchez ceci:

from django.db.models.loading import get_model
model = get_model('app_name', 'model_name')

Il existe d'autres méthodes, bien sûr, mais c'est la façon dont je le gérerais si vous ne savez pas quel fichier de modèles vous devez importer dans votre espace de noms. (Notez qu'il n'y a vraiment aucun moyen d'obtenir un modèle en toute sécurité sans savoir d'abord à quelle application il appartient. Regardez le code source pour loading.py si vous voulez tester votre chance à itérer sur tous les modèles des applications.)

Mise à jour: selon la chronologie de dépréciation de Django , django.db.models.loading a été obsolète dans Django 1.7 et sera supprimé dans Django 1.9. Comme indiqué dans la réponse Alasdair , une nouvelle API pour le chargement dynamique des modèles a été ajoutée à Django 1.7.

36
répondu Daniel Naab 2017-05-23 12:17:30

Pour Django 1.7+, il existe un registre d'applications . Vous pouvez utiliser le apps.get_model méthode pour obtenir dynamiquement un modèle.

from django.apps import apps
MyModel = apps.get_model('app_label', 'MyModel')
33
répondu Alasdair 2015-09-16 09:14:55
from django.authx.models import User
model = User
model.objects.all()
3
répondu 2009-01-04 22:34:45

Modèle = django.authx.modèle.Utilisateur

? Django renvoie une erreur, "mondial le nom django n'est pas défini."

Django ne renvoie pas l'erreur. Python le fait.

Tout d'abord, vous devez importer le modèle. Vous devez l'importer avec

from django.authx.models import User

Deuxièmement, si vous obtenez une erreur que django n'est pas défini, Django n'est pas installé correctement. Vous devez avoir Django sur votre PYTHONPATH ou installé dans vos paquets Python lib/site.

Pour installer Django correctement, voir http://docs.djangoproject.com/en/dev/intro/install/#intro-install

1
répondu S.Lott 2009-01-04 23:42:46

Les Classes sont des objets "de première classe" en Python, ce qui signifie qu'ils peuvent être passés et manipulés comme tous les autres objets.

Les modèles sont des classes - vous pouvez dire du fait que vous créez de nouveaux modèles en utilisant des instructions de classe:

class Person(models.Model):
    last_name = models.CharField(max_length=64)

class AnthropomorphicBear(models.Model):
    last_name = models.CharField(max_length=64)

Les identificateurs Person et AnthropomorphicBear sont liés aux classes Django, vous pouvez donc les transmettre. Cela peut être utile si vous souhaitez créer des fonctions d'assistance qui fonctionnent au niveau du modèle (et partagent une interface commune):

def print_obj_by_last_name(model, last_name):
    model_name = model.__name__
    matches = model.objects.filter(last_name=last_name).all()
    print('{0}: {1!r}'.format(model_name, matches))

Donc print_obj_by_last_name fonctionne avec les modèles Person ou AnthropomorphicBear. Il suffit de passer le modèle comme suit:

print_obj_by_last_name(model=Person, last_name='Dole')
print_obj_by_last_name(model=AnthropomorphicBear, last_name='Fozzy')
0
répondu cdleary 2009-01-04 23:43:50

Si vous avez le nom du modèle passé comme une chaîne, je suppose qu'une façon pourrait être

modelname = "User"
model = globals()[modelname]

Mais se moquer de globals () peut être un peu dangereux dans certains contextes. Donc, Manipulez avec soin :)

-2
répondu Hannes Ovrén 2009-01-04 22:40:44