Sitemap
Level Up Coding

Coding tutorials and news. The developer homepage gitconnected.com && skilled.dev && levelup.dev

Preferred by Professionals: Django + Pre-Commit

Django ❤️ Pre-Commit

4 min readFeb 25, 2024

--

Hi everyone, thank you for supporting my first article in the Professional Series: DataTables. Let’s discuss today what pre-commit is and how it can make our lives easier, saving us from humiliation in some moments.

Press enter or click to view image in full size
Image credit Unsplash

Pre-Commit

Pre-Commit is a tool that helps you manage and maintain clean and consistent code in your projects. It allows you to automatically check your code for issues before you commit it to your version control system, like Git.

Imagine you’re working on a project with a team, and everyone has their own coding style. Some prefer tabs for indentation, others prefer spaces. Some like to keep lines under a certain length, while others don’t mind longer lines. With pre-commit, you can set up rules to enforce a consistent style across the entire project.

When you run git commit, pre-commit will automatically run the checks you've configured. If any issues are found, it will prevent the commit from happening, giving you a chance to fix them before committing your changes. This helps ensure that your codebase stays clean and easy to read, which is especially important when working in a team.

PreCommit In Action

First let’s install it with pip.

pip install pre-commit

Don’t forget to activate the virtual environment.

Initialize PreCommit inside a project.

pre-commit install

(venv) ~/django/tutorial 22:25:57 $ pre-commit install
pre-commit installed at .git/hooks/pre-commit

Make sure you are inside a git repo.

Add pre-commit configuration

First create a file named .pre-commit-config.yaml in project root.

Get Rahul Beniwal’s stories in your inbox

Join Medium for free to get updates from this writer.

Let me share my pre-commit configs from one of my django project then we will dive deeper in the config file.

default_language_version:
python: python3.11.5

repos:
- repo: https://github.com/ambv/black
rev: 24.2.0
hooks:
- id: black

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: fix-encoding-pragma
- id: trailing-whitespace
- id: debug-statements
- id: name-tests-test
- id: check-json
- id: check-merge-conflict
- id: check-yaml

- repo: local
hooks:
- id: check-collectstatic
name: Check if static files need to be collected
entry: ./manage.py collectstatic --dry-run --noinput
language: system
types: [python]
pass_filenames: false

- id: check-deploy-ready
name: Check if the project is ready to be deployed
entry: ./manage.py check --deploy
language: system
types: [python]
pass_filenames: false

- id: check-migrations
name: Check if the project has unapplied migrations
entry: ./manage.py makemigrations --check --dry-run
language: system
types: [python]
pass_filenames: false
  • default_language_version: Specifies the default version of Python to use for hooks that require a Python interpreter.
  • repos: Starts a list of repositories containing hooks to be used in the pre-commit configuration.
  • - repo: https://github.com/ambv/black : Specifies the repository URL for the black code formatter.
  • rev: 24.2.0 : Specifies the version of the black code formatter to use.
  • hooks: Starts a list of hooks to be included from the black repository.
  • - id: black: Specifies the black hook to be included from the black repository.
  • - repo: https://github.com/pre-commit/pre-commit-hooks : Specifies the repository URL for the pre-commit-hooks repository.
  • Later hooks are defined in pre-commit-hooks repo. Mine fav is debug-statements which report for any pdb or ipdb startement left in code.
  • - repo: local : Specifies a local repository, meaning the hook is defined within the same .pre-commit-config.yaml file.
  • - id: check-migrations: Specifies the check-migrations hook to be included from the local repository. This hooks check for conflict migrations.
  • entry: ./manage.py makemigrations --dry-run: Specifies the command to run for the hook, checking Django migrations without actually creating missings.
  • language: system: Specifies that the hook should be run using the system's Python interpreter.
  • types: [python] : Specifies that this hook should only be run on Python files.
  • pass_filenames: false : Specifies that filenames should not be passed to the hook as arguments.

Testing Hooks

I am adding breakpoint() in my code which act as adding debugger.

class Login(View):

def get(self, request):
import pdb

pdb.set_trace()
return render(request, "login.html")

On commit it fails.

  debug statements (python)................................................Failed
- hook id: debug-statements
- exit code: 1

user/views.py:16:8: pdb imported

Oh it saved me.

Conclusion

Keeping things automated is a great strategy to save time and fix common mistakes while working on larger projects with a team. Pre-Commit is very useful, as we can create new hooks as per our requirements.

If you want to ignore pre-commit hooks on a commit, which is not recommended but can be done, use the following:

git commit --no-verify -m "test"

To learn more about pre-commit and available hooks you can check 👇

Hope you found it helpful. Follow Rahul Beniwal for more articles. Other click-worthy articles by me.

--

--

Rahul Beniwal
Rahul Beniwal

Written by Rahul Beniwal

I can help you master Python | Backend | System Design | Django | Rust | Computer Science | Databases | Making complex concepts clear and accessible with code