追溯性地将新的ManyToManyField默认值设置为现有模型

Sya*_*man 6 python django model

我有一个Django模型(称为BiomSearchJob),它目前正在运行,我想添加一个新的多对多关系,以使系统更易于为用户定制.以前,用户可以在不指定一组TaxonomyLevelChoices但不向系统添加更多功能的情况下提交作业,用户现在应该可以选择自己的分类级别.

这是模型:

class TaxonomyLevelChoice(models.Model):
    taxon_level = models.CharField(
        verbose_name="Taxonomy Chart Level", max_length=60)
    taxon_level_proper_name = models.CharField(max_length=60)

    def __unicode__(self):
        return self.taxon_level_proper_name

class BiomSearchJob(models.Model):
    ...
    # The new many-to-many relation
    taxonomy_levels = models.ManyToManyField(
        'TaxonomyLevelChoice', blank=False, max_length=3,
        default=["phylum", "class", "genus"])

    name = models.CharField(
        null=False, blank=False, max_length=100, default="Unnamed Job",
        validators=[alphanumeric_spaces])
    ...
Run Code Online (Sandbox Code Playgroud)

目前,所有现有的BiomSearchJobs隐含地具有default=术语中列出的三个分类级别(不是用户可选择的),因此在数据库中都是相同的.运行后migrate,我发现以前的作业不会立即具有三个分类级别关系,它们只在调用时返回一个空集job.taxonomy_levels.all()(如果job是实例BiomSearchJob).

有没有办法追溯性地添加这种关系而无需手动浏览所有内容?理想情况下,运行一个命令migrate,我想现有的BiomSearchJobs拥有phylum,class以及genus在上市taxonomy_levels属性.

ste*_*ppo 8

我认为您正在寻找数据迁移,这是一种允许仅对数据库进行数据更改的迁移.

你可以这样创建它:

python manage.py makemigrations <your app> --name=retroactively_add_levels
Run Code Online (Sandbox Code Playgroud)

然后将此代码插入刚刚创建的迁移文件中:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations


def add_taxonomy_levels(apps, schema_editor):
    BiomSearchJob = apps.get_model('<your app>', 'BiomSearchJob')
    TaxonomyLevelChoice = apps.get_model('<your app>', 'TaxonomyLevelChoice')
    for job in BiomSearchJob.objects.all():
        for choice in TaxonomyLevelChoice.objects.filter(taxon_level_proper_name__in=["phylum", "class", "genus"]):
            job.taxonomy_levels.add(choice)

class Migration(migrations.Migration):

   dependencies = []

operations = [
    migrations.RunPython(add_taxonomy_levels, reverse_code=migrations.RunPython.noop)
]
Run Code Online (Sandbox Code Playgroud)

它的工作原理与SQL查询一样,但它可以利用Django ORM.

希望这可以帮助.