Code Quality & Linting
Learn tools and practices for maintaining high code quality in Django projects.
65 min•By Priygop Team•Last updated: Feb 2026
Code Quality Tools
Maintaining high code quality is essential for long-term project success. Various tools help enforce coding standards and identify potential issues.
Linting & Code Analysis
Example
# Code Quality Tools Setup
# requirements-dev.txt (Development dependencies)
flake8==6.0.0
black==23.3.0
isort==5.12.0
pylint==2.17.4
mypy==1.3.0
bandit==1.7.5
pre-commit==3.3.2
# .flake8 configuration
[flake8]
max-line-length = 88
extend-ignore = E203, W503
exclude =
.git,
__pycache__,
.venv,
venv,
env,
migrations,
staticfiles,
media
# Black configuration (pyproject.toml)
[tool.black]
line-length = 88
target-version = ['py39']
include = '\.pyi?$'
extend-exclude = '''
/(
# directories
\.eggs
| \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/
'''
# isort configuration (pyproject.toml)
[tool.isort]
profile = "black"
multi_line_output = 3
line_length = 88
known_django = "django"
known_first_party = "myapp"
sections = ["FUTURE", "STDLIB", "DJANGO", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
# Pylint configuration (.pylintrc)
[MASTER]
disable=
C0114, # missing-module-docstring
C0115, # missing-class-docstring
C0116, # missing-function-docstring
[FORMAT]
max-line-length=88
[MESSAGES CONTROL]
disable=
C0103, # invalid-name
C0301, # line-too-long
R0903, # too-few-public-methods
R0913, # too-many-arguments
# MyPy configuration (pyproject.toml)
[tool.mypy]
python_version = "3.9"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
warn_unreachable = true
strict_equality = true
[[tool.mypy.overrides]]
module = [
"django.*",
"django_extensions.*",
]
ignore_missing_imports = true
# Pre-commit hooks (.pre-commit-config.yaml)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-merge-conflict
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
language_version: python3
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
- repo: https://github.com/pycqa/bandit
rev: 1.7.5
hooks:
- id: bandit
args: [-r, ., -f, json, -o, bandit-report.json]
# Custom Django management command for code quality
# management/commands/check_code_quality.py
from django.core.management.base import BaseCommand
import subprocess
import sys
class Command(BaseCommand):
help = 'Check code quality using various tools'
def add_arguments(self, parser):
parser.add_argument(
'--fix',
action='store_true',
help='Automatically fix formatting issues'
)
def handle(self, *args, **options):
tools = [
('Black', ['black', '--check', '.']),
('isort', ['isort', '--check-only', '.']),
('Flake8', ['flake8', '.']),
('Pylint', ['pylint', 'myapp/']),
('MyPy', ['mypy', '.']),
('Bandit', ['bandit', '-r', '.']),
]
failed_tools = []
for tool_name, command in tools:
self.stdout.write(f'Running {tool_name}...')
try:
result = subprocess.run(
command,
capture_output=True,
text=True
)
if result.returncode == 0:
self.stdout.write(
self.style.SUCCESS(f'{tool_name}: PASSED')
)
else:
self.stdout.write(
self.style.ERROR(f'{tool_name}: FAILED')
)
self.stdout.write(result.stdout)
self.stdout.write(result.stderr)
failed_tools.append(tool_name)
except FileNotFoundError:
self.stdout.write(
self.style.WARNING(f'{tool_name}: Not installed')
)
if failed_tools:
self.stdout.write(
self.style.ERROR(
f'Code quality checks failed for: {", ".join(failed_tools)}'
)
)
sys.exit(1)
else:
self.stdout.write(
self.style.SUCCESS('All code quality checks passed!')
)
# Usage: python manage.py check_code_quality
# GitHub Actions workflow for code quality
# .github/workflows/code-quality.yml
name: Code Quality
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
- name: Run Black
run: black --check .
- name: Run isort
run: isort --check-only .
- name: Run Flake8
run: flake8 .
- name: Run Pylint
run: pylint myapp/
- name: Run MyPy
run: mypy .
- name: Run Bandit
run: bandit -r . -f json -o bandit-report.json
# IDE Configuration (VS Code)
# .vscode/settings.json
{
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.linting.pylintEnabled": true,
"python.linting.mypyEnabled": true,
"python.formatting.provider": "black",
"python.sortImports.args": ["--profile", "black"],
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
"python.linting.flake8Args": ["--max-line-length=88"],
"python.linting.pylintArgs": ["--max-line-length=88"]
}