开发者

Automatic solution for "Add a related_name argument to the definition for 'XXX'."?

I'm plugging Django 开发者_如何学编程into an existing system. I have been given a legacy schema, and I have to work with it.

I have generated models with inspectdb, but I'm getting hundreds of:

ABC>DEF: Accessor for field 'HIJ' clashes with related field 'KLM'. Add a related_name argument to the definition for 'HIJ'.

I wouldn't have a problem with this if it were only a small number. But it isn't.

Is there any automatic way to fix this by adding unique related_names?

EDIT: For clarification, I do am looking for an automatic solution to the problem, not one that involves editing each field by hand.


Occasionally I find myself in this situation. Modifying inspectdb has worked for me in several instances but I can't promise it'll be appropriate in every situation. Here's what I've done:

    #Original inspectdb
    121                         if rel_to in known_models:
    122                             field_type = 'ForeignKey(%s' % rel_to
    123                         else:
    124                             field_type = "ForeignKey('%s'" % rel_to

    #Modified inspectdb
    121                         if rel_to in known_models:
    122                             field_type = 'ForeignKey(%s' % rel_to
    123                         else:
    124                             field_type = "ForeignKey('%s'" % rel_to
    125                         extra_params['related_name'] = '%s_%s' % (table2model(table_name),column_to_field_name[column_name])

This will automatically add a related_name argument to every generated model that isn't likely to collide with any others. Again, it depends on the situation, but this single line modification has saved me tons of work.


If you don't need the related name, you can set it to "+".

If you don't want to disable them completely or cannot use "+" in your django version (I can't remember when it was added), you may use something like the following:

_no_related_name_counter = 0
def no_related_name():
    _no_related_name_counter += 1
    return "_norn_%%(class)s_%i" % _no_related_name_counter

ForeignKey(..., related_name=no_related_name())

But if you insert related names with a regexp search and replace, you may as well set them to something readable, e.g. replace (\s*(\w+)\s*=\s*models\.ForeignKey\(.*)\)(\s*)$ with $1, related_name="%(class)s_$2_reverse")$3


You should check the foreign key relationships by specifying the related_name, like this:

user = models.ForeignKey(User, related_name='user')
admin = models.ForeignKey(User, related_name='user1') #you need to use a different related_name here

Hope it helps.


If you want to deal with large legacy database and dont want to use '+' you can run a simple script to modify the generated models.py file as follows:

import fileinput
textToSearch = "models.DO_NOTHING"

_no_related_name_counter = 1000

with fileinput.FileInput('models.py', inplace=True, backup='.bak') as file:
    for line in file:
        _no_related_name_counter += 1
        textToReplace = 'models.DO_NOTHING, related_name="%(class)s_{}"'.format(_no_related_name_counter)
        print(line.replace(textToSearch, textToReplace), end='')
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜