无法使用Django 3.0.3中的Migrations API使用ModelState和ProjectState进行迁移

如何解决无法使用Django 3.0.3中的Migrations API使用ModelState和ProjectState进行迁移

我正在使用ProjectState迁移到表的新属性。我正在尝试使用Django 3.0.3。中的迁移API来了解ModelState和ProjectState。

我无法迁移到具有新字段的新状态。有人可以ProjectStateModelState使用什么来申请新的model_deFinition迁移工作吗?以下代码不会迁移到数据库,但不会出现任何错误

我想从数据库表状态迁移到另一个状态,并且有一些元数据_Meta

  • 当前数据库状态model_state.fields为:

    [('id',<django.db.models.fields.AutoField>)]

  • 添加model_state.fields迁移之后的未来数据库状态fields_attrs应该是使用models_deFinition的状态:

    [('id',<django.db.models.fields.AutoField>),('name',<django.db.models.fields.CharField>)]

模型定义代码为:

model_config对象是

{
 '__module__': 'testmodule','app_label': 'testmodule','__unicode__': <function ModelScript.model_create_config.<locals>.<lambda> at 0x00000221B6FBEF70>,'attrs': {'name': <django.db.models.fields.CharField>}
}

model_deFinition是:

model_deFinition = type(
                model_item.table_name,# Todo: Put this into Database
                # model_config.get("extends"),bases,model_config
            )

这是我正在使用的代码

from django.db.migrations.state import ProjectState
from django.db.migrations.migration import Migration
from django.db.migrations.state import ModelState
from django.db.migrations import operations

# model_deFinition is coming from a function as the following object
model_deFinition = {'__module__': 'testmodule','__unicode__': <function ModelScript.model_create_config.<locals>.<lambda> at 0x000002047275FF70>,'attrs': {'name': <django.db.models.fields.CharField>},'__doc__': 'SampleModel(id)','_Meta': <Options for SampleModel>,'DoesNotExist': <class 'testmodule.SampleModel.DoesNotExist'>,'MultipleObjectsReturned': <class 'testmodule.SampleModel.MultipleObjectsReturned'>,'id': <django.db.models.query_utils.DeferredAttribute object at 0x00000204727F9430>,'objects': <django.db.models.manager.ManagerDescriptor object at 0x00000204727F9490>}

model_state = ModelState.from_model(model_deFinition)

# field_attrs are all the new fields to be migrated         
for k,v in field_attrs.items():
    model_state.fields.append((k,v))

# Create a fake migration with the CreateModel operation
cm = operations.CreateModel(name=model_state.name,fields=model_state.fields)

migration = Migration("fake_migration",model_state.app_label)
migration.operations.append(cm)

# SHOULD ProjectState be used for the new deFinition to be APPLIED to DB and HOW?
state = ProjectState()
with db_conn.schema_editor(collect_sql=True,atomic=migration.atomic) as schema_editor:
     # Following create_model also doesnot migrate to MysqL DB
     # Gives a Table exists Error even with root user of MysqL
     # schema_editor.create_model(model_deFinition)

     # Following doesnot migrate to the new required state
     state = migration.apply(state,schema_editor,collect_sql=True)
     # Following gives atomic transaction error if used along with atomic
     # following commit commented gives no error but doesnt migrate
     # db_conn.commit()

我已阅读并使用How to programmatically generate the CREATE TABLE SQL statement for a given model in Django?

欢迎任何帮助或资源。

更新:我确实尝试了Django的测试用例,但无法以编程方式工作。我必须分类使用addfield吗?不确定如何使它工作。 projectstate和model_create方式都不起作用

解决方法

开始时,您需要使用模型元类,即。 ModelBase ,而不是 type

from django.db.models.base import ModelBase

model_definition = ModelBase(
    model_item.table_name,bases,model_config
)

一旦使用了正确的元类,由于使用的是内部 ModelBase 设置的许多类属性,您可能会收到无数错误。不希望您自己定下来。

除了转储模型具有的所有属性外,您应该只设置 ModelBase 期望在传统模型上设置的属性,其中包括:

  • __module__ __qualname__
  • 模型字段
  • 客户经理或查询集
  • 模型方法
  • 模型 Meta

所有其他内容都应省略。

例如,如果您有一个看起来像这样的模型,请在模块 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'

这些模型的动态版本需要如下所示:

from django.db import models
from django.db.models.base import ModelBase

bases = (models.Model,)

Parent = ModelBase('Parent',{
    '__module__': 'myapp.models','__qualname__': 'Parent','name': models.CharField(max_length=45),})

Child = ModelBase('Child','__qualname__': 'Child','parent': models.ForeignKey('myapp.Parent',on_delete=models.CASCADE),})

ModelWithMeta = ModelBase('ModelWithMeta','__qualname__': 'ModelWithMeta','Meta': type('Meta',(),{'db_table': 'some_table'}),})

我不了解您的迁移代码的用途,因此我将假定它是试图使动态模型正常工作的一种方法,这意味着您可以将其完全抛弃并使用内置的迁移加载器,即:

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

如果您不熟悉python metaclasses ,我建议您仔细阅读它们,因为这是理解我的代码的先决条件。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?