tarantino - Django: Obtener modelo de cadena?
django tutorial (8)
A partir de Django 1.9, el método es
django.apps.AppConfig.get_model(model_name)
.
- danihp
A partir de Django 1.7,
django.db.models.loading
está en desuso (se eliminará en 1.9) a favor del nuevo sistema de carga de aplicaciones.
- Scott Woodall
Lo encontré. Está definido aquí:
from django.db.models.loading import get_model
Definido como:
def get_model(self, app_label, model_name, seed_cache=True):
En Django, puede especificar relaciones como:
author = ForeignKey(''Person'')
Y luego internamente tiene que convertir la cadena "Persona" en la Person
modelo.
¿Dónde está la función que hace esto? Quiero usarlo, pero no puedo encontrarlo.
A partir de Django 1.7, django.db.models.loading
está en desuso (se eliminará en 1.9) a favor del nuevo sistema de carga de aplicaciones. Los 1.7 documentos nos dan lo siguiente en su lugar:
$ 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
<class ''django.contrib.auth.models.User''>
>>>
Editado por tttthomasssss comentario.
Aquí hay un enfoque menos específico de django para obtener una clase de una cadena:
mymodels = [''ModelA'', ''ModelB'']
model_list = __import__(''<appname>.models'', fromlist=mymodels)
model_a = getattr(model_list, ''ModelA'')
o puede usar importlib como se muestra here :
import importlib
myapp_models = importlib.import_module(''<appname>.models'')
model_a = getattr(myapp_models, ''ModelA'')
En caso de que no sepa en qué aplicación existe su modelo, puede buscarlo de esta manera:
from django.contrib.contenttypes.models import ContentType
ct = ContentType.objects.get(model=''your_model_name'')
model = ct.model_class()
Recuerde que su_model_name debe estar en minúscula.
La bendita forma de hacer esto en Django 1.7+ es:
import django
model_cls = django.apps.apps.get_model(''app_name'', ''model_name'')
Entonces, en el ejemplo canónico de todos los tutoriales marco:
import django
entry_cls = django.apps.apps.get_model(''blog'', ''entry'') # Case insensitive
La mayoría de las "cadenas" del modelo aparecen como la forma "nombredeaplicación.nombredelmodelo", por lo que es posible que desee utilizar esta variación en get_model
from django.db.models.loading import get_model
your_model = get_model ( *your_string.split(''.'',1) )
La parte del código django que generalmente convierte esas cadenas en un modelo es un poco más compleja. Esto proviene 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)
Para mí, este parece ser un buen caso para dividir esto en una sola función en el código central. Sin embargo, si sabe que sus cadenas están en formato "Modelo de aplicación", las dos líneas anteriores funcionarán.
No estoy seguro de dónde se hace en Django, pero podrías hacer esto.
Asignando el nombre de la clase a la cadena a través de la reflexión.
classes = [Person,Child,Parent]
def find_class(name):
for clls in classes:
if clls.__class__.__name__ == name:
return clls
solo para que alguien se quede atascado (como yo):
from django.apps import apps
model = apps.get_model(''app_name'', ''model_name'')
app_name
debe aparecer en la lista usando comillas, como debe ser el model_name
(es decir, no intente importarlo)
get_model
acepta minúsculas o mayúsculas ''model_name''