Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easy way to set on_delete across entire application

Tags:

regex

django

I've been using the -Wd argument for Python and discovered tons of changes I need to make in order to prepare my upgrade to Django 2.0

python -Wd manage.py runserver

The main thing is that on_delete is due to become a required argument.

RemovedInDjango20Warning: on_delete will be a required arg for ForeignKey in Django 2.0. Set it to models.CASCADE on models and in existing migrations if you want to maintain the current default behavior.

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

Is there an easy regex (or way) I can use to put on_delete into all of my foreign keys?

like image 215
Sayse Avatar asked Jan 10 '17 14:01

Sayse


2 Answers

Use with care

You can use

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

This will search for all foreign keys that currently do not already define what happens upon deletion and also ignores anywhere you have overridden ForeignKey.

It will then capture anything inside the brackets which allows you to replace the inner text with the capture group plus the on_delete

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

It is not advised to do a replace all with the above, and you should still step through to ensure no issues are created (such as any pep8 line length warnings)

like image 123
Sayse Avatar answered Oct 19 '22 04:10

Sayse


I had to do this, and Sayse 's solution worked:

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='')
like image 41
eugene Avatar answered Oct 19 '22 04:10

eugene