首页 > 编程问答 >Django 将现有字段更改为外键

Django 将现有字段更改为外键

时间:2024-07-26 11:04:54浏览次数:12  
标签:python python-3.x django django-migrations

我有一个 Django 模型,以前看起来像这样:

class Car(models.Model):
    manufacturer_id = models.IntegerField()

还有另一个模型,称为 Manufacturer id 字段引用了该模型。但是,我意识到使用 Django 的内置外键功能会很有用,因此我将模型更改为:

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer)

此更改似乎立即可以正常工作,查询可以正常工作,没有错误,但是当我尝试运行迁移时,Django 输出以下内容:

- Remove field manufacturer_id from car
- Add field manufacturer to car

执行此迁移将清除数据库中的所有现有关系,因此我不想这样做。我真的根本不需要任何迁移,因为像 Car.objects.get(manufacturer__name="Toyota") 这样的查询工作正常。我想要一个适当的数据库外键约束,但它不是一个高优先级。

所以我的问题是:有没有办法进行迁移或其他方法,允许我将现有字段转换为外键?我无法使用 --fake ,因为我需要在开发、产品和同事的计算机上可靠地工作。


虽然Django的迁移系统非常强大,但它并不擅长将现有列转换为外键而不丢失数据。你已经观察到它会尝试删除旧列并添加一个新列,这会导致数据丢失。

以下是一些在不丢失数据的情况下实现目标的方法:

1. 使用SQL语句手动迁移

这是最直接和最可靠的方法,特别是当你对SQL比较熟悉时。

  1. 创建迁移文件但不执行任何操作: bash python manage.py makemigrations --empty yourapp
  2. 编辑迁移文件:
  3. 删除自动生成的操作 (删除和添加列)。
  4. 添加一个 RunSQL 操作,该操作将添加外键约束,但不会修改列本身: ```python from django.db import migrations, models

    class Migration(migrations.Migration): dependencies = [ ('yourapp', 'previous_migration'), ]

     operations = [
         migrations.RunSQL(
             "ALTER TABLE yourapp_car ADD CONSTRAINT fk_manufacturer FOREIGN KEY (manufacturer_id) REFERENCES yourapp_manufacturer (id) DEFERRABLE INITIALLY DEFERRED;",
             reverse_sql='ALTER TABLE yourapp_car DROP CONSTRAINT fk_manufacturer;',
         ),
     ]
    

    3. **应用迁移:** bash python manage.py migrate ```

注意:

  • yourapp 替换为你的应用程序名称。
  • yourapp_car yourapp_manufacturer 替换为你的表名。
  • DEFERRABLE INITIALLY DEFERRED 部分是可选的,它允许推迟外键约束检查,直到事务结束。这在处理大量数据或可能存在现有数据不一致的情况时非常有用。

2. 使用第三方库

一些第三方库可以帮助简化此过程。一个流行的选择是 django-south ,它提供更强大的迁移功能。但是, django-south 已经不再积极维护,并且与较新版本的Django不兼容。

3. 分阶段迁移

如果你无法使用手动SQL或第三方库,则可以使用以下步骤分阶段进行迁移:

  1. 添加新的外键字段: python class Car(models.Model): manufacturer_id = models.IntegerField() manufacturer = models.ForeignKey(Manufacturer, null=True, blank=True, on_delete=models.SET_NULL)
  2. 使用 null=True blank=True 允许该字段为空。
  3. 选择合适的 on_delete 行为。

  4. 运行迁移: bash python manage.py makemigrations python manage.py migrate

  5. 编写脚本以填充新字段: ```python from yourapp.models import Car, Manufacturer

for car in Car.objects.all(): car.manufacturer = Manufacturer.objects.get(id=car.manufacturer_id) car.save() ```

  1. 删除旧字段并更新数据库约束:
  2. 与步骤1类似,使用 RunSQL 操作删除旧列并更新外键约束以使其不再可为空。

选择哪种方法取决于你的具体情况和对不同工具的熟悉程度。

标签:python,python-3.x,django,django-migrations
From: 66803323

相关文章

  • python安装第三方库的国内镜像
    直接:pipconfigsetglobal.index-urlhttps://pypi.doubanio.com/simple设置了全局的第三方库的下载文件镜像请求网址。安装第三方库:pipinstallscrapy--scrapy第三方库名称 pip从国内镜像安装的命令使用中国大陆地区的Python包镜像服务时,可以通过修改p......
  • 如何将Python嵌入.Net?
    我尝试基于文档此处和此处使用pythonnet将Python嵌入到.Net中。这是我的代码Runtime.PythonDLL=@"D:\Dev\Console\.conda\python311.dll";PythonEngine.Initialize();dynamicsys=Py.Import("sys");Console.WriteLine("Pythonversion:&quo......
  • 使用pybind11封装c++的dll,供python调用
    用pip安装好pybind11 文件清单,都写在一个目录里//文件名:add.cppextern"C"doubleadd(doublein1,doublein2){returnin1+in2;}//文件名:sub.cppextern"C"doublesub(doublein1,doublein2){returnin1-in2;}//文件名:mul.cppextern"......
  • python-myStudyList
     1  下载软件1.1下载python最新版本并安装下载地址:百度搜索python官网。WelcometoPython.org。 1.2官网学习网页:PythonTutorials–RealPython   1.3也可以下载集成环境软件Anaconda。 Anaconda软件商城官方正版免费下载(msc23.cn) 2 ......
  • Python语法基础
    基本语句输入input() eg:输出print(内容)注释单行注释:#注释内容多行注释:"""注释内容"""数据类型: 字面量:整型、浮点数、字符串......intfloatstring查看数据类型:type(数据)查看数据类型 转换函数int(x):将x转换成整数类型float(x):将x转......
  • PyTesseract 不提取文本?我是所有这些Python的新手,请需要h3lp
    它不想从图像中提取文本,就像终端保持黑色并带有空格,就像它实际上试图提取文本一样,这是我的代码和图像从PIL导入图像导入pytesseract导入CV2“C:\用户\埃米利亚诺\下载\practic.png”pytesseract.pytesseract.tesseract_cmd="C:\ProgramFiles\Tesseract-OCR\tesseract.exe......
  • Python安装第三方库
    Python安装PILPIL(PythonImagingLibrary)是一个旧的Python库,用于处理图像。然而,PIL已经不再维护,并被一个名为Pillow的库所取代。Pillow是PIL的一个分支,并且完全兼容PIL。建议使用Pillow而不是PIL。pipinstallpillowPython安装moviepymoviepy是一个用于视频编辑的Python库,......
  • 优化Python中图像中的OCR文本检测
    我目前正在用python编写一个程序,该程序获取包含大量文本的图像,将其提取到.txt文件,然后将找到的单词与另一个文件中的单词列表进行比较,并创建一些坐标(根据像素)在图像中找到的单词中,如果找到图像,则会在图像中绘制红色方块。到目前为止,我已经正确处理了坐标部分,在单词周围绘制了......
  • Python保存字典类型数据到文件的三种方法
    1、在Python中使用pickle模块的dump函数将字典保存到文件中importpicklemy_dict={'Apple':4,'Banana':2,'Orange':6,'Grapes':11}#保存文件withopen("myDictionary.pkl","wb")astf:pickle.dump(my_dict,tf)......
  • 《最新出炉》系列入门篇-Python+Playwright自动化测试-53- 处理面包屑(详细教程)
    1.简介面包屑(Breadcrumb),又称面包屑导航(BreadcrumbNavigation)这个概念来自童话故事“汉赛尔和格莱特”,当汉赛尔和格莱特穿过森林时,不小心迷路了,但是他们发现沿途走过的地方都撒下了面包屑,让这些面包屑来帮助他们找到回家的路。所以,面包屑导航的作用是告诉访问者他们在网站中......