【问题标题】:Easy way to set on_delete across entire application在整个应用程序中设置 on_delete 的简单方法
【发布时间】:2017-05-25 02:05:41
【问题描述】:

我一直在使用 Python 的 -Wd 参数,并发现我需要进行 项更改以准备升级到 Django 2.0

python -Wd manage.py runserver

主要是on_delete 将成为必需的参数。

RemovedInDjango20Warning: on_delete 将是 Django 2.0 中 ForeignKey 的必需参数。如果您想保持当前的默认行为,请在模型和现有迁移中将其设置为 models.CASCADE

https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.ForeignKey.on_delete

有没有一种简单的正则表达式(或方法)可以用来将on_delete 放入我的所有外键中?

【问题讨论】:

    标签: regex django


    【解决方案1】:

    小心使用

    你可以使用

    (ForeignKey|OneToOneField)\(((?:(?!on_delete|ForeignKey|OneToOneField)[^\)])*)\)
    

    这将搜索当前尚未定义删除时发生的所有外键,并且还会忽略您已覆盖 ForeignKey 的任何位置。

    然后它将捕获括号内的任何内容,从而允许您将内部文本替换为捕获组加上 on_delete

    $1($2, on_delete=models.CASCADE)
    

    不建议全部替换为上述内容,您仍应逐步执行以确保未产生任何问题(例如任何 pep8 行长度警告)

    【讨论】:

    • 这很有帮助,谢谢。请注意,它不匹配多行表达式。
    • 另外值得注意的是,这将错误地捕获没有on_deleteGenericForeignKey。此外,GenericForeignKey 通常在没有任何参数的情况下被实例化,因此此正则表达式会将这些行更改为 foo = GenericForeignKey(, on_delete=models.CASCADE),这在无效的 Python 中。无论如何,这是一个巨大的节省时间。谢谢!
    【解决方案2】:

    我必须这样做,而 Sayse 的解决方案奏效了:

    import re
    import fileinput
    
    import os, fnmatch
    import glob
    from pathlib import Path
    
    
    # https://stackoverflow.com/questions/41571281/easy-way-to-set-on-delete-across-entire-application
    # https://stackoverflow.com/questions/11898998/how-can-i-write-a-regex-which-matches-non-greedy
    # https://stackoverflow.com/a/4719629/433570
    # https://stackoverflow.com/a/2186565/433570
    
    regex = r'(.*?)(ForeignKey|OneToOneField)\(((?:(?!on_delete|ForeignKey|OneToOneField)[^\)])*)\)(.*)'
    
    index = 0
    for filename in Path('apps').glob('**/migrations/*.py'):
        print(filename)
    =>  filename = (os.fspath(filename), ) # 3.6 doesn't have this
    
        for line in fileinput.FileInput(filename, inplace=1):
            a = re.search(regex, line)
            if a:
                print('{}{}({}, on_delete=models.CASCADE){}'.format(a.group(1), a.group(2), a.group(3), a.group(4)))
            else:
                print(line, end='')
    

    【讨论】:

    【解决方案3】:

    我制作了这个可能对你有帮助的 bash 脚本。

    #!/bin/bash
    FK=()
    IFS=$'\n'
    count=0
    for fk in $(cat $1 | egrep -i --color -o 'models\.ForeignKey\((.*?)');
    do
        FK[$count]=$fk
        #FK+=$fk
        count=$(($count + 1))
    done
    
    for c in "${FK[@]}"; 
    do 
        r=`echo "${c}" | sed -e 's/)$/,on_delete=models.CASCADE)/g'`
        a="${c}"
        sed -i "s/${c}/${r}/g" $1
    done
    

    也许您想要一种更“节省”的方法,将 sed -i 更改为 sed -e 并将输出重定向到一个文件以与您的原始 models.py 文件进行比较。

    编码愉快!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-15
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多