Pour commencer, vous avez besoin utiliser la métaclasse de modèle , c'est à dire. ModelBase
, et non type
:
from django.db.models.base import ModelBase
model_definition = ModelBase(
model_item.table_name,
bases,
model_config
)
Une fois que vous utilisez la bonne métaclasse , vous recevrez probablement une myriade d'erreurs, car vous utilisez de nombreux attributs de classe que ModelBase
définit en interne et ne s'attend pas à ce que vous vous définissiez vous-même.
Au lieu de vider tous les attributs de votre modèle, vous ne devez définir que les attributs que ModelBase
s'attend à être défini sur un modèle traditionnel, qui comprend :
__module__
et__qualname__
- champs de modèle
- Gestionnaires personnalisés ou ensembles de requêtes
- méthodes du modèle
- modèle
Meta
Tout le reste doit être omis.
Ainsi, par exemple, si vous avez un modèle qui ressemble à ceci, dans le module myapp.models
:
class Parent(models.Model):
name = models.CharField(max_length=45)
class Child(models.Model):
name = models.CharField(max_length=45)
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
class ModelWithMeta(models.Model):
class Meta:
db_table = 'some_table'
La version dynamique de ces modèles doit ressembler à ceci :
from django.db import models
from django.db.models.base import ModelBase
bases = (models.Model,)
Parent = ModelBase('Parent', bases, {
'__module__': 'myapp.models',
'__qualname__': 'Parent',
'name': models.CharField(max_length=45),
})
Child = ModelBase('Child', bases, {
'__module__': 'myapp.models',
'__qualname__': 'Child',
'name': models.CharField(max_length=45),
'parent': models.ForeignKey('myapp.Parent', on_delete=models.CASCADE),
})
ModelWithMeta = ModelBase('ModelWithMeta', bases, {
'__module__': 'myapp.models',
'__qualname__': 'ModelWithMeta',
'Meta': type('Meta', (), {'db_table': 'some_table'}),
})
Je ne comprends pas le but de votre code de migration, donc je supposerai qu'il s'agissait d'un piratage pour tenter de faire fonctionner les modèles dynamiques, ce qui signifie que vous pouvez probablement le jeter complètement et utiliser le chargeur de migration intégré, c'est-à-dire :
python3 manage.py makemigrations myapp && python3 manage.py migrate myapp
Si vous n'êtes pas familier avec python metaclasses
, je vous recommande de les lire, car c'est un prérequis pour comprendre mon code.