Skip to content

Commit 4547c0a

Browse files
fadedDexofanatodorov
authored andcommitted
Fixes #208 Support recursive (self) ForeignKey relations
1 parent 443415f commit 4547c0a

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

pylint_django/tests/input/func_noerror_foreignkeys.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ def get_username(self):
5555
return self.user.username
5656

5757

58+
class Human(models.Model):
59+
child = ForeignKey('self', on_delete=models.SET_NULL, null=True)
60+
parent = ForeignKey(to='self', on_delete=models.SET_NULL, null=True)
61+
62+
def get_grandchild(self):
63+
return self.child.child
64+
65+
def get_grandparent(self):
66+
return self.parent.parent
67+
68+
5869
class UserPreferences(models.Model):
5970
"""
6071
Used for testing FK which refers to another model by

pylint_django/transforms/foreignkey.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from itertools import chain
22

3-
from astroid import MANAGER, nodes, InferenceError, inference_tip, UseInferenceDefault
3+
from astroid import (
4+
MANAGER, nodes, InferenceError, inference_tip,
5+
UseInferenceDefault
6+
)
47
from astroid.nodes import ClassDef, Attribute
58

69
from pylint_django.utils import node_is_subclass
@@ -42,8 +45,17 @@ def infer_key_classes(node, context=None):
4245
break
4346
elif isinstance(arg, nodes.Const):
4447
try:
45-
# can be 'Model' or 'app.Model'
46-
module_name, _, model_name = arg.value.rpartition('.')
48+
# can be 'self , 'Model' or 'app.Model'
49+
if arg.value == 'self':
50+
module_name = ''
51+
# for relations with `to` first parent be Keyword(arg='to')
52+
# and we need to go deeper in parent tree to get model name
53+
if isinstance(arg.parent, nodes.Keyword) and arg.parent.arg == 'to':
54+
model_name = arg.parent.parent.parent.parent.name
55+
else:
56+
model_name = arg.parent.parent.parent.name
57+
else:
58+
module_name, _, model_name = arg.value.rpartition('.')
4759
except AttributeError:
4860
break
4961

0 commit comments

Comments
 (0)