diff --git a/pylint_django/augmentations/__init__.py b/pylint_django/augmentations/__init__.py index 1150bd69..99c33840 100644 --- a/pylint_django/augmentations/__init__.py +++ b/pylint_django/augmentations/__init__.py @@ -63,8 +63,46 @@ class ModelB(models.Model): warn. """ quack = False - - if node.attrname.endswith('_set'): + # Note: it would have been nice to import the Manager object from Django and + # get its attributes that way - and this used to be the method - but unfortunately + # there's no guarantee that Django is properly configured at that stage, and importing + # anything from the django.db package causes an ImproperlyConfigured exception. + # Therefore we'll fall back on a hard-coded list of attributes which won't be as accurate, + # but this is not 100% accurate anyway. + manager_attrs = ( + 'none', + 'all', + 'count', + 'dates', + 'distinct', + 'extra', + 'get', + 'get_or_create', + 'create', + 'bulk_create', + 'filter', + 'aggregate', + 'annotate', + 'complex_filter', + 'exclude', + 'in_bulk', + 'iterator', + 'latest', + 'order_by', + 'select_for_update', + 'select_related', + 'prefetch_related', + 'values', + 'values_list', + 'update', + 'reverse', + 'defer', + 'only', + 'using', + 'exists', + ) + + if node.attrname in manager_attrs or node.attrname.endswith('_set'): # if this is a X_set method, that's a pretty strong signal that this is the default # Django name, rather than one set by related_name quack = True @@ -72,46 +110,6 @@ class ModelB(models.Model): # we will if isinstance(node.parent, Getattr): func_name = getattr(node.parent, 'attrname', None) - - # Note: it would have been nice to import the Manager object from Django and - # get its attributes that way - and this used to be the method - but unfortunately - # there's no guarantee that Django is properly configured at that stage, and importing - # anything from the django.db package causes an ImproperlyConfigured exception. - # Therefore we'll fall back on a hard-coded list of attributes which won't be as accurate, - # but this is not 100% accurate anyway. - manager_attrs = ( - 'none', - 'all', - 'count', - 'dates', - 'distinct', - 'extra', - 'get', - 'get_or_create', - 'create', - 'bulk_create', - 'filter', - 'aggregate', - 'annotate', - 'complex_filter', - 'exclude', - 'in_bulk', - 'iterator', - 'latest', - 'order_by', - 'select_for_update', - 'select_related', - 'prefetch_related', - 'values', - 'values_list', - 'update', - 'reverse', - 'defer', - 'only', - 'using', - 'exists', - ) - if func_name in manager_attrs: quack = True @@ -124,7 +122,9 @@ class ModelB(models.Model): pass else: for cls in inferred: - if node_is_subclass(cls, 'django.db.models.base.Model'): + if (node_is_subclass( + cls, 'django.db.models.manager.Manager') + or node_is_subclass(cls, 'django.db.models.base.Model')): # This means that we are looking at a subclass of models.Model # and something is trying to access a _set attribute. # Since this could exist, we will return so as not to raise an