如何在Django数据迁移上下文中访问模型的自定义管理器?

9q78igpj  于 12个月前  发布在  Go
关注(0)|答案(4)|浏览(105)

我在我的几个模型中使用了一个自定义模型管理器。这个管理器有助于加速DB插入。我需要执行数据迁移,它涉及到迁移数百万条记录/对象。我需要在我的数据迁移中使用我的自定义管理器。有人知道如何获得它吗?在数据迁移上下文中,如果我运行model.objects,这会返回Django的模型管理器。

guicsvcw

guicsvcw1#

到目前为止,我正在使用的方法,似乎工作可靠,是为模型示例化一个本地Manager,然后将manager的model属性设置为我感兴趣的模型:

class MyManager(Manager):
    ...
    def my_create_func(self):
        ...

class MyModel(Model):
    ...
    objects = MyManager()

def data_migration(apps, schema_editor):
    model = apps.get_model(...)
    manager = MyManager()
    manager.model = model
    manager.my_create_func()

字符串

uhry853o

uhry853o2#

您还可以使用Manager的use_in_migrations属性(docs):

class MyManager(models.Manager):
    use_in_migrations = True

class MyModel(models.Model):
    objects = MyManager()

字符串

7gs2gvoe

7gs2gvoe3#

为什么不直接导入你的模型?

from myproj.models import MyModel
MyModel.objects.filter(field=value).update(field=new_value)

字符串

uwopmtnx

uwopmtnx4#

这让我今天。

如何在自定义RunPython Django迁移中使用自定义管理器的方法

假设你已经有了这个模型及其自定义管理器:

# e.g. in myapp.managers file
class MyModelManager(models.Manager):
    def do_something_special():
        # ... your clever database manipulation

# in myapp.models file
class MyModel(models.Model):
    #... various fields

    objects = MyModelManager()

字符串
当您试图通过直接将Model导入到迁移中来使用它时,会发生这样的错误:

def my_custom_migration_function__forwards(apps, schema_editor):
    from myapp.models import MyModel
    MyModel.objects.do_something_special()  # Custom Manager method

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0001_an_earlier_migration')
    ]

    operations = [
        #... Other migration steps such as CreateModel or AddField etc...,
        migrations.RunPython(my_custom_migration_function__forwards, reverse_code=migrations.RunPython.noop)
    ]

# Raises: 
#    'do_something_special': Could not find an 'apps.get_model("...", "MyModel")'
#    Importing the model directly is incorrect for data migrations.
#    'do_something_special': Model variable name MyModel is different from the model class name that was found in the apps.get_model(...)


当你有一个自定义的模型方法,而迁移看不到的时候,会发生这样的错误:

def my_custom_migration_function__forwards(apps, schema_editor):
    MyModel = apps.get_model('myapp', 'MyModel')
    MyModel.objects.do_something_special()  # Custom Manager method

# Raises: *AttributeError: Manager has no do_something_special*


在43TesseractsAnswer的基础上,解决方案分为四个部分:

A)将use_in_migrations = True放入Manager类中:

# e.g. in myapp.managers.py file
class MyModelManager(models.Manager):
    use_in_migrations = True   # << Add this

B)在终端中使用makemigrations生成迁移

./manage.py makemigrations


您会发现一个新的迁移是由一个migrations生成的。

C)移植迁移,AlterModelManagers从新的迁移迁移到您自定义迁移的正确位置:

def my_custom_migration_function__forwards(apps, schema_editor):
    from myapp.models import MyModel
    MyModel.objects.do_something_special()  # Custom Manager method

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0001_an_earlier_migration')
    ]

    operations = [
        #... Other migration steps such as CreateModel or AddField etc...,
        migrations.AlterModelManagers(  # << GRAFT THIS IN
            name='mymodel',
            managers=[
                ('objects', 
myapp.managers.MyModelManager()),
            ],
        ),
        migrations.RunPython(my_custom_migration_function__forwards, reverse_code=migrations.RunPython.noop)
    ]

D)删除自动创建的迁移

您已经将该步骤移植到早期的迁移中,因此不再需要它。

相关问题