如何修改已经在数据库中迁移的模型? [英] How to modify a models who's already migrated in Database?

查看:72
本文介绍了如何修改已经在数据库中迁移的模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是django的新手,我想修改我的模型(已经在sqlite3数据库中)了,而又不影响整个项目.上次修改模型时,我花了几个小时才能修复它,因为我对整个项目进行了修改.所以我不想犯同样的错误,请你们帮我帮忙?感谢您的帮助

I am new to django, I want to modify my models (Which is already in my sqlite3 database) without bugging my entire project. Last time I modified my models it took me hours to fix it cause I bugged the whole project. So I dont want to make the same error, could you guys help me witht the commands please? Thanks for helping

models.py(目前)

models.py (at the moment)

from django.db import models

THE_GENDER = [
    ("Monsieur", "Monsieur"),
    ("Madame", "Madame")
]


class Post(models.Model):


    name = models.CharField(max_length=100)
    email = models.CharField(max_length=100)
    gender = models.CharField(max_length=8, choices=THE_GENDER)
    number = models.CharField(max_length=100)


    def __str__(self):
        return self.name

我要对模型进行的编辑(我想在模型中添加一个作者用户.所以我知道是谁在制作表单.)

The edit that I want to make to the models (I want to add an author user into the models. So i know whos making the form.)

from django.db import models
from django.contrib.auth.models import User

THE_GENDER = [
    ("Monsieur", "Monsieur"),
    ("Madame", "Madame")
]


class Post(models.Model):


    name = models.CharField(max_length=100)
    email = models.CharField(max_length=100)
    gender = models.CharField(max_length=8, choices=THE_GENDER)
    number = models.CharField(max_length=100)
    author = models.ForeignKey(User, on_delete=models.CASCADE)


    def __str__(self):
        return self.name

我的admin.py文件(不确定是否生病需要将其保留不变或进行修改)

my admin.py files (not sure If ill need to leave it the same or modify it)

from django.contrib import admin
from .models import Post

admin.site.register(Post)

我的forms.py文件

my forms.py files

from django import forms
from .models import Post
from crispy_forms.helper import FormHelper


class post_form(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(post_form, self).__init__(*args, **kwargs)

        self.helper = FormHelper(self)

    class Meta:
        model = Post
        fields = ["name", "email", "gender", "number"]


views.py

from django.shortcuts import render
from django.http import HttpResponse
from .forms import post_form


# Create your views here.
def home(request):
    form = post_form(request.POST or None)
    if form.is_valid():
        form.save()

    context = {
        "form": form
    }


    return render(request, "sms/home.html", context)

推荐答案

要详细说明我在上面的评论...

To elaborate on my comment above...

在Django中添加新的不可为空的ForeignKey通常是一个三步过程.

Adding a new non-nullable ForeignKey in Django is generally a three-step process.

  1. 首先,使用null=True将新的ForeignKey添加到模型定义中,然后运行makemigrations.这将创建一个迁移,该迁移将添加该字段,对此没有什么特别的.执行此迁移将添加一列,其中所有行均以NULL作为值.
  2. 第二,为同一应用程序(makemigrations --empty)创建一个新的空迁移,然后编辑该迁移以包含数据迁移步骤.在这里,您需要根据业务逻辑为新的外键选择一些值.
  3. 第三,您修改模型定义中的ForeignKey以设置null=False,并使用makemigrations创建第三个迁移. Django会询问您是否以某种方式处理了null –您需要说是的,我发誓我拥有"(自从您开始,在上面的第2步中).
  1. First, you add the new ForeignKey to your model definition with null=True, and run makemigrations. This will create a migration that will add the field, nothing special about it. Executing this migration will add a column with all rows having NULL as the value.
  2. Second, you create a new empty migration for the same app (makemigrations --empty), then edit that migration to contain a data migration step. This is where you'll need to, according to your business logic, choose some value for the new foreign key.
  3. Third, you modify the ForeignKey in your model definition to set null=False and create a third migration with makemigrations. Django will ask whether you've dealt with nulls somehow – you need to say that "yep, I swear I have" (since you did, above in step 2).

实际上,对于OP问题的简化版本,我们要在其中添加用户外键:

In practice, for a simplified version of OP's question where we'll want to add an User foreign key:

class Post(models.Model):
    name = models.CharField(max_length=100)

1a.添加可为空的字段.

class Post(models.Model):
    name = models.CharField(max_length=100)
    author = models.ForeignKey(User, null=True, on_delete=models.CASCADE))

1b.运行makemigrations.

$ python manage.py makemigrations
Migrations for 'something':
  something/migrations/0002_post_author.py
    - Add field author to post

2a.创建一个新的空迁移.

$ python manage.py makemigrations something --empty -n assign_author
Migrations for 'something':
  something/migrations/0003_assign_author.py

2b.编辑迁移文件.

与往常一样,可以找到有关数据迁移的更多信息,在手册中.

from django.db import migrations


def assign_author(apps, schema_editor):
    User = apps.get_model('auth', 'User')  # or whatever is your User model
    Post = apps.get_model('something', 'Post')  # or wherever your Post model is
    user = User.objects.filter(is_superuser=True).first()  # Choose some user...
    assert user  # ... and ensure it exists...
    Post.objects.all().update(author=user)  # and bulk update all posts.


class Migration(migrations.Migration):

    dependencies = [...]

    operations = [
        migrations.RunPython(assign_author, migrations.RunPython.noop),
    ]

3a.使该字段不可为空.

class Post(models.Model):
    name = models.CharField(max_length=100)
    author = models.ForeignKey(User, null=False, on_delete=models.CASCADE))

3b.运行Makemigrations.

如实回答这个问题–您刚刚​​添加了RunPython操作.

3b. Run Makemigrations.

Answer truthfully to the question – you've just added a RunPython operation.

$ python manage.py makemigrations something -n post_author_non_null
You are trying to change the nullable field 'author' on something. to non-nullable without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Ignore for now, and let me handle existing rows with NULL myself (e.g. because you added a RunPython or RunSQL operation to handle NULL values in a previous data migration)
 3) Quit, and let me add a default in models.py
Select an option: 2
Migrations for 'something':
  something/migrations/0004_post_author_non_null.py
    - Alter field author on post

全部完成!

运行migrate现在将运行这三个迁移,并且您的模型将具有author而不会丢失数据.

All done!

Running migrate will now run these three migrations and your model will have author without data loss.

这篇关于如何修改已经在数据库中迁移的模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆