Puedo ver esta pregunta en 2 perspectivas
- Forma normal de crear dinámicamente una clase de Python
- Crea modelos dinámicos de django específicamente
Pero en ambos casos, los atributos deben definirse como dict con el nombre de la variable y su valor. Porque definir una variable sin un valor no tiene sentido aquí.
1. Forma normal de crear dinámicamente una clase de Python
Aquí simplemente podemos usar el método type () para generar una clase de Python. Esto se puede usar más tarde para crear objetos con su propio nombre agregándolos a la función incorporada locals ().
A continuación se menciona un ejemplo
classes = ["Class1", "Class2"]
class_fileds = [
{
'cl1_var1': "test",
'cl1_var2': 123,
},
{
'cl2_var1': [1, 2, 3],
}
]
classes_details = list(zip(classes, class_fileds)) # Python3 format
for class_details in classes_details:
class_name = class_details[0]
class_attrs = class_details[1]
class_def = type(
class_name,
(object, ), # Base classes tuple
class_attrs
)
locals().update({class_name: class_def}) # To associate the class with the script running
instance1 = Class1()
instance2 = Class2()
Salidas
>>> instance1 = Class1()
>>> instance2 = Class2()
>>>
>>> instance1.cl1_var1
'test'
>>> instance1.cl1_var2
123
>>> instance2.cl2_var1
[1, 2, 3]
Aquí, los nombres de clase en la lista, classes = ["Class1", "Class2"], se pueden usar como tal, es decir, Class1 (), Class2 (), etc. Esto se logra agregando las variables Class1 y Class2 a la ejecución script dinámicamente utilizando la función incorporada local ()
2. Cree modelos dinámicos de Django específicamente
Aunque la lógica básica sigue siendo la misma, se requieren un par de cambios.
En primer lugar, debemos comprender las creaciones de modelos dinámicos en Django. Django proporciona una documentación clara para esto.
Consulte, https://code.djangoproject.com/wiki/DynamicModels
Se puede ver un ejemplo a continuación, puede agregar directamente el siguiente script al archivo models.py
from django.db import models
from django.db.models import CharField, IntegerField
# This is taken from https://code.djangoproject.com/wiki/DynamicModels#Ageneral-purposeapproach
def create_model(name, fields=None, app_label='', module='', options=None, admin_opts=None):
class Meta:
pass
if app_label:
setattr(Meta, 'app_label', app_label)
if options is not None:
for key, value in options.iteritems():
setattr(Meta, key, value)
attrs = {'__module__': module, 'Meta': Meta} # Set up a dictionary to simulate declarations within a class
if fields: # Add in any fields that were provided
attrs.update(fields)
model = type(name, (models.Model,), attrs) # Create the class, which automatically triggers ModelBase processing
return model
classes = ["Class1", "Class2"]
class_fileds = [
{
'cl1_var1': CharField(max_length=255),
'cl1_var2': IntegerField(),
},
{
'cl2_var2': IntegerField(),
}
]
models_details = list(zip(classes, class_fileds))
for model_detail in models_details:
model_name = model_detail[0]
model_attrs = model_detail[1]
model_def = create_model(
model_name,
fields=model_attrs,
app_label=__package__,
module= __name__,
)
locals()[model_name] = model_def
Salida en django shell
>>> from my_app.models import Class1
>>> Class1(cl1_var1="Able to create dynamic class", cl1_var2=12345).save()
>>> Class1.objects.all().values()
<QuerySet [{'cl1_var1': 'Able to create dynamic class', 'id': 3, 'cl1_var2': 12345}]>
Este modelo se agrega a la aplicación django, my_app y esto funcionaría bien y hay algunas cosas a tener en cuenta
- los atributos de campo deben manejarse con cuidado ya que lo leerá del archivo de texto
- Los modelos deben agregarse usando locals () para importar eso desde la aplicación
- Método, create_model debe tomarse del enlace de referencia, ya que admite más funciones, como agregar páginas de administración, etc.
- La migración de datos también funciona con este tipo de modelo
Mi sugerencia
Los métodos explicados anteriormente funcionarían sin ningún problema y todos son compatibles, pero una cosa que no debe olvidarse es que hay una diferencia de rendimiento en las clases importadas dinámicamente y la importación real. Además, esta es una estructura un poco compleja y cualquier cambio en el código debe hacerse con mucho cuidado para no romperlo.
Entonces, mi sugerencia es leer el archivo de texto con configuraciones y generar el archivo models.py desde el archivo de configuración usando algún script mágico (que también se puede crear en Python). Entonces, cada vez que haya un cambio en el archivo de configuración de texto, debe generar el script models.py. De esta manera también puede garantizar las definiciones del modelo