Skip to content

Code Conventions

MedUX is a large project, so consistent coding conventions are important. This page documents the rules that apply across the codebase.

Code Style

Use Ruff for both formatting and linting. Run it before every commit (venv active):

ruff format .
ruff check . --fix

Or use pre-commit to run it automatically:

pre-commit run --all-files

Set up your IDE to format with Ruff on save.

Language

  • Code (variable names, functions, classes): English
  • Docstrings and comments: English
  • User-facing strings: English, wrapped in gettext_lazy for translation
  • Translations: managed via Django's i18n framework (makemessages / compilemessages)

Django CRUD Naming

MedUX follows Django's naming conventions for views, permissions, URL names, and JavaScript events:

View class name Permission View name URL segment JS adjective
ListView view list
DetailView view detail
CreateView add add add added
UpdateView change update change changed
DeleteView delete delete delete deleted

Example URL patterns:

urlpatterns = [
    path("/", PersonListView.as_view(), name="list"),
    path("add/", PersonCreateView.as_view(), name="add"),
    path("<pk>/", PersonDetailView.as_view(), name="detail"),
    path("<pk>/change/", PersonUpdateView.as_view(), name="update"),
    path("<pk>/delete/", PersonDeleteView.as_view(), name="delete"),
]

HTMX Event Naming

Custom JavaScript events follow this pattern (all lowercase):

<app_name>:<model_name>:<adjective>

The adjective should match the CRUD verb: added, deleted, changed. If you don't need separate events for add/delete, use changed for everything.

Example:

class PersonUpdateView(...):
    def form_valid(self, form):
        return HttpResponseEmpty(
            headers={
                "HX-Trigger": "core:person:changed",
            }
        )
<div hx-get="{% url 'person:list' %}"
     hx-trigger="load once, core:person:changed from:body">

Imports

  • Use absolute imports
  • Group imports: stdlib, third-party, Django, project
  • Let Ruff sort imports automatically (isort rules are included)

Type Hints

  • Use type hints for function signatures
  • Use from __future__ import annotations for forward references
  • Prefer built-in generic types (list[str] over List[str])

Testing

  • Use pytest with pytest-django
  • Test files go in a tests/ directory within each app
  • See Testing for details