Unable to migrate using ModelState and ProjectState using of migrations API in Django 3.0.3

前端 未结 1 1985
礼貌的吻别
礼貌的吻别 2021-01-14 05:23

I am using ProjectState to migrate to a new attributes of a table. I am trying to understand the ModelState and ProjectState using of migrations API in Django 3.0.3.

相关标签:
1条回答
  • 2021-01-14 06:08

    To start, you need to be using the model metaclass, ie. ModelBase, and not type:

    from django.db.models.base import ModelBase
    
    model_definition = ModelBase(
        model_item.table_name,
        bases,
        model_config
    )
    

    Once you use the proper metaclass, you will likely receive a myriad of errors, since you are using many class attributes that ModelBase sets internally, and is not expecting you to set yourself.

    Instead of dumping all the attributes that your model has, you should only set the attributes that ModelBase expects to be set on a traditional model, which includes:

    • __module__ and __qualname__
    • model fields
    • custom managers or querysets
    • model methods
    • model Meta

    Everything else should be omitted.

    So for example, if you have a models that look like this, in the 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'
    

    The dynamic version of these models need to look like this:

    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'}),
    })
    

    I don't understand the purpose of your migration code, so I will assume that it was a hack in attempt to get the dynamic models working, which means you can probably throw it out altogether and use the builtin migration loader, ie:

    python3 manage.py makemigrations myapp && python3 manage.py migrate myapp
    

    I you aren't familiar with python metaclasses, I'd recommend reading up on them, since it's a prerequisite to understand my code.

    0 讨论(0)
提交回复
热议问题