当前位置: 首页 > news >正文

心理咨询网站建设做网站为什么要服务器

心理咨询网站建设,做网站为什么要服务器,网站设计与建设课程,网站制作主要公司TL;DR 永远不要相信 makemigrations! migrate 之前一定好好看看 migrate 了啥东西,必要时手动修改生成的 migrate 文件。 最好把db的更新与服务代码更新解耦 场景 先描述下场景: 现在有两个表,一个是 question,一…

TL;DR

永远不要相信 makemigrations!

migrate 之前一定好好看看 migrate 了啥东西,必要时手动修改生成的 migrate 文件。

最好把db的更新与服务代码更新解耦

场景

先描述下场景:

现在有两个表,一个是 question,一个是 choice,其中 question 和 choice 是一对多的关系,其中 choice 表中会记录 question_id(此时不是外键约束)。

class Question(models.Model):content = models.CharField(max_length=256, blank=True, default='')class Choice(models.Model):content = models.CharField(max_length=256, default='')question_id = models.IntegerField(null=True)

现在我想把 question_id 改为外键,所以很自然的改写 model:

class Question(models.Model):content = models.CharField(max_length=256, blank=True, default='')class Choice(models.Model):content = models.CharField(max_length=256, default='')question = models.ForeignKey(Question, on_delete=models.DO_NOTHING) 

然后快乐地执行 makemigration -> migrate,然后 choice 里面的 question_id 就全没了(实际上我还手贱加了个 default,导致都关联到 default 的 question 上了),然后第二天因为左脚先进办公室被开了。。。

原因

在自己的 demo 上复现了下。

问题出在 makemigrate 生成的文件上,解析出来的 operations 是先把 question_id 列 remove 掉(RemoveField),然后再加上(AddField)。。。

这样设计的思路我不是很懂,可能是有些 engine(比如SQLite)不支持对现有的表加外键?

解决

修改 migration 文件,把先 remove 再 add 的逻辑调整一下。

需要用到 migration.RunPython,migration 文件应该长成下边这样:

from django.db import migrations, models
import django.db.models.deletiondef duplicate_question_id(apps, schema_editor):Choice = apps.get_model("polls", "Choice")for c in Choice.objects.all():Question = apps.get_model("polls", "Question")q = Question.objects.get(id=c.question_id)c.question_cpy = qc.save()class Migration(migrations.Migration):# 一些必要的依赖,这里大概率不用改dependencies = []operations = [migrations.AddField(model_name="choice",name="question_cpy",# question_cpy 先把 question_id 列的数据 copy 过来field=models.ForeignKey(null=True,on_delete=django.db.models.deletion.DO_NOTHING,to="polls.question",),),migrations.RunPython(code=duplicate_question_id,reverse_code=migrations.RunPython.noop,# reverse_code 是 migrate 回退时会执行的操作# noop 方法是为了支持回退的空方法),migrations.RemoveField(model_name="choice",name="question_id",),migrations.RenameField(model_name="choice",old_name="question_cpy",new_name="question",),]

注意:你需要根据实际情况编写合适的代码,上面仅提供思路。

如果你是在sqlite上测试,可以正常 migrate,但是外键不会生效(因为 sqlite 默认关闭外键)。

如果在 mysql 上测试,应该是可以成功的(待验证)。

除了 RunPython 之外还可以用RunSQL,然后仔细确定SQL的合法性,个人感觉会更安全一些,毕竟直接操作 DB 的部分,普遍会认为潜在风险较高,会对相应动作有更高的敏感度。(不过最关键的还是要感知 makemigrations 其实不是个靠谱的东西)

又跟了下这个问题,发现在 AlterField 里面指定外键的 db_column,然后再 rename 成 model 里面指定的 name 即可实现上述需求,类似:

		migrations.AlterField(model_name="choice",name="question_id",field=models.ForeignKey(name='question',to='polls.question',on_delete=django.db.models.deletion.DO_NOTHING,db_column='question_id',null=False),),migrations.RenameField(model_name="choice",old_name="question_id",new_name="question",)

这里还有些需要注意的地方,migration 整体上是通过 DDL 事务执行的,但是有些 SQL 引擎不支持DDL 事务(比如 MySQL),所以可能会出现 migrate 不成功然后无法回滚的情况(一个 migration 可能会对应两条 SQL 语句),需要关注。

避免

永远不要相信 makemigrations!

最好把db的更新与服务代码更新解耦

Django 还提供了 sqlmigrate 这个命令,可以看对应的 migrations 动作具体会解析成哪些 sql 语句执行,可以在 merge 之前把对应的 sql 语句进行一次 review。

推荐

migrate 其实分 code state 和 db state 两部分,可以把这两部分开设置:change field name with no db impact

http://www.yayakq.cn/news/696566/

相关文章:

  • 怎样建设大型网站wordpress 社交链接
  • 南通网站排名优化价格网站设计案例公司
  • 域名备案要先做网站的吗微信h5的制作方法
  • 自个做网站教程建站教程流程图
  • 站长源码商城微网站创建
  • 网站搭建团队做网站送商标
  • o2o网站系统建设微网站和网站同步像素
  • 中国农业工程建设协会网站舆情分析网站免费
  • 网站开发中设置会员等级常宁网站制作
  • 百度收录网站入口哪家app定制开发好
  • 怎么做免费推广网站做专业网站设计多少钱
  • 台州网络建站模板芜湖seo网站优化
  • vi手册网站制作优化推广
  • 宁夏百度网站怎么做建设教育网站
  • 快速开发工具网站网络设计的内容是什么
  • 网站建设不用虚拟主机建立网站要钱吗
  • 网上服务大厅官网免费的关键词优化软件
  • 炒股配资网站开发红安建设局投诉网站
  • 站长seo微商城网站建设效果
  • 电子商务网站开发流程免费提升学历
  • 网站后期的维护建设银行信用卡网站
  • 企业网站建设所需要的资料南宁vi设计公司
  • 青岛个人接网站建设被跨境电商骗了怎么办
  • 网站如何建设二级域名代理wordpress编辑图片
  • 优化方案官方网站php免费源码网站
  • wordpress娃娃插件深圳网络营销优化
  • 大连网站建设外贸wordpress首页文章
  • 深圳app网站设计企业邮箱价格
  • 网站开发接入本地天地图vs做的网站案例
  • 网站建设 代表联系群众网站开发的基础是什么