Django migrationsSouth。新建列从同一记录中取默认值的另一个值。

问题描述 投票:3回答:3

我想在一个已经存在的表中添加一个新的列,但我想根据已经存在的数据给它一个默认值。

例如,每条记录都有一个 start_date. 现在我想添加一个 open_until 列,而我想用 start_date 每个现有记录的值。(即将到来的记录将可以选择不同的值)

有什么友好的方法可以做到这一点吗?

sql django migration django-south relational
3个回答
13
投票

你也可以在South中这样做。唯一需要注意的是,你需要两个步骤。

  1. A 模式迁移 增加了open_until列

    from django.db import models
    import datetime
    
    class MyModel(models.Model):
        start_date = models.DateField(),
        open_until = models.DateField(default=datetime.date.today),
    

    $ python manage.py schemamigration --auto appname

  2. A 数据迁移 用其他列的值填充现有的行。

    $ python manage.py datamigration appname populate_open_until

    import datetime
    
    class Migration(DataMigration):
    
        def forwards(self, orm):
            "Set open_until value to that of start_date for existing rows"
            for t in orm.MyModel.objects.all():
                t.open_until = t.start_date
                t.save()
    
        def backwards(self, orm):
            "Revert back to default"
            for t in orm.MyModel.objects.all():
                t.open_until = datetime.date.today
                t.save()
    

(可选)在步骤1中,你可以提供一个临时的默认值,或者使其成为可选的,并添加第三步。

  1. A 模式迁移 这使得open_until列成为强制性的。

0
投票

在 Python 3.8 中,我首先向 MyApp 模型文件,它看起来像。

from django.db import models
import datetime

class MyModel(models.Model):
    start_date = models.DateField(),
    open_until = models.DateField(default=datetime.date.today),

然后,在运行 manage.py makemigrations 添加这行到新创建的迁移文件中。

def forward(apps, schema_editor):
    my_model_objects = apps.get_model('MyApp', 'MyModel').objects.all()
    for t in my_model_objects:
        t.open_until = t.start_date
        t.save()

def reverse(apps, schema_editor):
    pass

class Migration(migrations.Migration):
    operations = [
        " the base operations is here " ,
        migrations.RunPython(forward, reverse),
    ]

-2
投票

正如我给你的回复,如果你使用的是框架,在数据库级别设置一个动态默认值是没有必要的 :)

我认为,最好的方法是在保存记录之前在视图中设置列的值。

从django.py中的models.py

from django.db import models

class MyModel(models.Model):
    start_date = models.DateField(),
    open_until = models.DateField(),

forms.py from django.forms import ModelForm

class MyForm(forms.ModelForm):
    model = MyModel

    fields = ('start_date')

景观类

from django.http import HttpResponse
from django.views.generic import CreateView
from .models import MyModel


MyView(CreateView):
    form_class = MyForm

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)
        if form.is_valid():
            submitted_form = form.save(commit=False)
            submitted_form.open_until = form.cleaned_data["start_date"]
            submitted_form.save()
            # return an HttpResponse here

对于前面的条目,做一个视图只调用一次,然后循环浏览所有记录,根据订单列的值保存新列的值。

类似这样。

from django.http import HttpResponse

def set_open_until_values(request)
    records = MyModel.objects.all()
    for record in records:
        record.open_until = record.start_date
        record.save()
    return HttpResponse("Done!!")
© www.soinside.com 2019 - 2024. All rights reserved.