Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Django 连接已存在的数据库(以 MySQL 为例)自动生成 models,并伪造数据库迁移 #143

Open
Qingquan-Li opened this issue Jan 5, 2020 · 0 comments
Labels

Comments

@Qingquan-Li
Copy link
Owner

Qingquan-Li commented Jan 5, 2020

环境:

  • Python 3.7
  • Django 2.2
  • MySQL 5.7.28

参考:

# 在 Django 项目的 settings.py 模块中配置好 MySQL 连接设置后,执行以下命令。
# create models by introspecting(内省) an existing database:
$ python manage.py inspectdb > models.py
# introspecting(内省),也叫类型内省,是在运行时进行的一种对象检测机制。
# 我们可以通过内省来获取一个对象的所有信息,比如这个对象的类型,其中包含哪些属性等等。

执行上一步,使用已有的数据库生成 models 后,执行下面数据库迁移命令。参考:

# 生成数据库迁移( app_label 是 Django 项目中的 APP 名称,选填)
# 注意需要先在 settings.py 的 INSTALLED_APPS 中添加 app_label
$ python manage.py makemigrations app_label

# 查看所有迁移
$ python manage.py showmigrations

# 应用数据库生成。由于数据库表已存在,无法应用初始迁移。
# 使用 --fake-initial 选项伪造此迁移。此时实际上只是添加了一条迁移记录,实际上并没有应用迁移。
$ python manage.py migrate --fake-initial app_label

# 还可以伪造迁移 app_label/migrations 下的某条记录(使用场景:再次使用旧有的数据库表生成 models ),例如:
$ python manage.py migrate --fake app_label 0001_initial

注意:
执行 $ python manage.py inspectdb > models.py 并使用其中的 model 应用(伪造)数据库迁移,此后,修改 model 中的字段之后可能无法生成新的数据库迁移记录。
此时,删除(或注释)model ,然后生成并应用数据库迁移(应用 delete model 的迁移记录);然后再还原修改过的 model ,即可成功生成和应用数据库迁移(应用 create model 的迁移记录)。

注意:
如果同一个 models.py 下有多个 model ,此时再次使用旧有的数据库表生成 models 之后,生成数据库迁移并伪造迁移这条记录之后,需要执行以下命令,才能在 Admin 管理后台为其他管理员设置这个 model 的权限。

$ python manage.py migrate app_label

附:

“Django 连接已存在的数据库(以 MySQL 为例)自动生成 models,并伪造数据库迁移”通常在本地环境而非生产环境(服务器环境)中进行。

所以部署 Django 项目到服务器时,并且本地使用的 MySQL 和生产环境的 MySQL 数据库是分离的,此时在 Django 项目的 settings.py 模块中配置好线上生产环境的 MySQL 连接设置(注释掉本地环境的 MySQL 连接配置)后,只需要执行以下正常的数据库迁移命令,不需要“伪造数据库迁移”:

$ python manage.py makemigrations
$ python manage.py migrate

如果在执行上面 $ python manage.py migrate 命令后,出现以下报错:

django.db.utils.IntegrityError: (1215, 'Cannot add foreign key constraint')

参考:https://stackoverflow.com/questions/28561458/django-mysql-error-when-creating-tables ,请先执行:

$ python manage.py migrate auth

然后再次执行:

$ python manage.py migrate

附:在项目中新建一个 app ,并第二次使用原来的某个数据库表(model)(作为外键使用)


在 Django 模型的 Meta 类( class Meta )中, managed 的默认值为 True 。 Django 会自动根据模型类生成映射的数据库表(对象关系映射 Object Relational Mapping,简称ORM)。

managed = True 时,Django 管理这些数据库表的生命周期。 Django 可以对数据库表进行创建、修改(migrations、migrate)和删除。

managed = False 告诉 Django 不要管理这些数据表的创建、修改和删除。


在项目中新建一个 app:

$ python manage.py startapp app02

在 app02/models.py 中第二次使用数据库原有的某个数据库表(model),主要是作为外键使用:

# This is an auto-generated Django model.
# 根据原有的数据库(这里是 MySQL)自定生成 model 的命令:$ python manage.py inspectdb > models.py
# 在项目根目录中生成一个 models.py 文件,这个 OmCustomer 类是从 models.py 中复制的。
class OmCustomer(models.Model):
    id = models.CharField(primary_key=True, max_length=40)
    created_by = models.CharField(max_length=40)
    ... ...

    class Meta:
        managed = False
        db_table = 'om_customer'

因为这个 model(数据表)已经被项目中另一个 app01 使用并管理了( managed = True ),如果此处注释掉 managed = False ,执行以下命令将会报错:

$ python manage.py makemigrations app02
SystemCheckError: System check identified some issues:

ERRORS: om_customer: (models.E028) db_table 'om_customer' is used by multiple models: app01.OmCustomer, app02.OmCustomer.
@Qingquan-Li Qingquan-Li changed the title Django 连接已存在的数据库自动生成 models Django 连接已存在的数据库自动生成 models,并伪造数据库迁移 Jan 5, 2020
@Qingquan-Li Qingquan-Li changed the title Django 连接已存在的数据库自动生成 models,并伪造数据库迁移 Django 连接已存在的数据库(以 MySQL 为例)自动生成 models,并伪造数据库迁移 Mar 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant