Skip to content
This repository has been archived by the owner on Nov 11, 2020. It is now read-only.

Commit

Permalink
Check admin classes not in admin.py
Browse files Browse the repository at this point in the history
This is because registering an admin class implies a call to
models.get_apps() which attempts to import *every* models.py in
the project.

Whilst your project should probably not have significant
inter-app dependencies, importing every possible models.py does
not help the situation and can cause ImportError when models are
loaded in different scenarios.

Signed-off-by: Chris Lamb <lamby@debian.org>
  • Loading branch information
lamby committed Mar 23, 2010
1 parent a690c21 commit 3697137
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
2 changes: 2 additions & 0 deletions DjangoLint/AstCheckers/__init__.py
Expand Up @@ -20,11 +20,13 @@

def register(linter):
from size import SizeChecker
from admin import AdminChecker
from settings import SettingsChecker
from model_fields import ModelFieldsChecker
from model_methods import ModelMethodsChecker

linter.register_checker(SizeChecker(linter))
linter.register_checker(AdminChecker(linter))
linter.register_checker(SettingsChecker(linter))
linter.register_checker(ModelFieldsChecker(linter))
linter.register_checker(ModelMethodsChecker(linter))
57 changes: 57 additions & 0 deletions DjangoLint/AstCheckers/admin.py
@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-

# django-lint -- Static analysis tool for Django projects and applications
# Copyright (C) 2008-2009 Chris Lamb <chris@chris-lamb.co.uk>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from pylint.interfaces import IASTNGChecker
from pylint.checkers import BaseChecker

from .utils import nodeisinstance

class AdminChecker(BaseChecker):
__implements__ = IASTNGChecker

name = 'django_admin'
msgs = {
'W8020': (
'Admin class %r not in admin.py',
'loldongs',),
}

ADMIN_BASE_CLASSES = (
'django.contrib.admin.options.ModelAdmin',
)

def visit_module(self, node):
self.module = node

def leave_class(self, node):
if not nodeisinstance(node, self.ADMIN_BASE_CLASSES):
return

if not self.module.file.endswith('admin.py'):
# Admin classes not in an app's admin.py can cause circular import
# problems throughout a project.
#
# This is because registering an admin class implies a call to
# models.get_apps() which attempts to import *every* models.py in
# the project.
#
# Whilst your project should probably not have significant
# inter-app dependencies, importing every possible models.py does
# not help the situation and can cause ImportError when models are
# loaded in different scenarios.
self.add_message('W8020', node=node, args=(node.name,))
7 changes: 7 additions & 0 deletions django_lint_example/example/models/__init__.py
@@ -1,4 +1,5 @@
from django.db import models
from django.contrib import admin

class NullableModel(models.Model):
TRUTH_VALUE = True
Expand Down Expand Up @@ -165,3 +166,9 @@ class WeirdPrimaryKeyModel(models.Model):
class ManyToManyModel(models.Model):
nullable = models.ManyToManyField(Model2, null=True)
blank = models.ManyToManyField(Model3, blank=True)

class AdminKlass(admin.ModelAdmin):
search_fields = ('nullable',)

class Meta:
model = ManyToManyModel

0 comments on commit 3697137

Please sign in to comment.