forms.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. """Models."""
  2. from astroid.nodes import Assign, AssignName, ClassDef
  3. from pylint.checkers import BaseChecker
  4. from pylint.checkers.utils import check_messages
  5. from pylint.interfaces import IAstroidChecker
  6. from pylint_django.__pkginfo__ import BASE_ID
  7. from pylint_django.utils import node_is_subclass
  8. def _get_child_meta(node):
  9. for child in node.get_children():
  10. if isinstance(child, ClassDef) and child.name == "Meta":
  11. return child
  12. return None
  13. class FormChecker(BaseChecker):
  14. """Django model checker."""
  15. __implements__ = IAstroidChecker
  16. name = "django-form-checker"
  17. msgs = {
  18. f"W{BASE_ID}04": (
  19. "Use explicit fields instead of exclude in ModelForm",
  20. "modelform-uses-exclude",
  21. "Prevents accidentally allowing users to set fields, especially when adding new fields to a Model",
  22. )
  23. }
  24. @check_messages("modelform-uses-exclude")
  25. def visit_classdef(self, node):
  26. """Class visitor."""
  27. if not node_is_subclass(node, "django.forms.models.ModelForm", ".ModelForm"):
  28. # we only care about forms
  29. return
  30. meta = _get_child_meta(node)
  31. if not meta:
  32. return
  33. for child in meta.get_children():
  34. if not isinstance(child, Assign) or not isinstance(child.targets[0], AssignName):
  35. continue
  36. if child.targets[0].name == "exclude":
  37. self.add_message(f"W{BASE_ID}04", node=child)
  38. break