Skip to main content

django-pint-field

Published on Django Packages PyPI Python versions Django versions Documentation License: MIT

Store, validate, and convert physical quantities in Django using Pint.

Why Django Pint Field?

Django Pint Field enables you to:

  • Store quantities (like 1 gram, 3 miles, 8.120391 angstroms) in your Django models
  • Edit quantities in forms with automatic unit conversion
  • Compare quantities in different units (e.g., compare weights in pounds vs. kilograms)
  • Display quantities in user-preferred units while maintaining accurate comparisons
  • Perform aggregations and lookups across different units of measurement

The package uses a PostgreSQL composite field to store both the magnitude and units, along with a base-unit comparator value for accurate comparisons. This approach ensures that users can work with their preferred units while maintaining data integrity and comparability. For this reason, the project only works with PostgreSQL databases.

Requirements

  • Python 3.11+
  • Django 4.2+
  • PostgreSQL database
  • Pint 0.24+

Installation

pip install django-pint-field

Add to your INSTALLED_APPS:

INSTALLED_APPS = [
    # ...
    "django_pint_field",
    # ...
]

Run migrations:

python manage.py migrate django_pint_field
Failure to run django-pint-field migrations before running migrations for models using PintFields will result in errors. The migration creates a required composite type in your PostgreSQL database.

Previous versions of the package added three composite types to the database. The newest migration modifies the columns with these types to use a single composite type.

Tips for Upgrading from Legacy django-pint-field

If using [django-pgtrigger](https://django-pgtrigger.readthedocs.io/en/latest/commands/) or other packages that depend on it (e.g.: django-pghistory), we highly recommend that you temporarily uninstall all triggers before running the django-pint-field migrations. It is also a good practice to make a backup of your database before running the migration. Users freshly installing `django-pint-field` do not need to worry about this warning.
python manage.py pgtrigger uninstall

Then run the migrations:

python manage.py migrate django_pint_field

Reinstall the triggers after the migrations are complete:

python manage.py pgtrigger install

Quick Start

  1. Define your model:
from decimal import Decimal
from django.db import models
from django_pint_field.models import DecimalPintField


class Product(models.Model):
    name = models.CharField(max_length=100)
    weight = DecimalPintField(
        default_unit="gram",
        unit_choices=["gram", "kilogram", "pound", "ounce"],
    )
  1. Use it in your code:
from django_pint_field.units import ureg

# Create objects
product = Product.objects.create(
    name="Coffee Bag",
    weight=ureg.Quantity(Decimal("340"), "gram"),
)

# Query using different units
products = Product.objects.filter(
    weight__gte=ureg.Quantity(Decimal("0.5"), "kilogram"),
)

# Access values
print(product.weight)  # 340 gram
print(product.weight.quantity)  # 340 gram (accessing the Pint Quantity object)
# Convert to different units
print(product.weight.quantity.to("kilogram"))  # 0.340 kilogram
print(product.weight.kilogram)  # 0.340 kilogram
print(product.weight.kilogram__2)  # 0.34 kilogram  (rounded to 2 decimal places)

Features

Field Types

  • IntegerPintField: For whole number quantities
  • DecimalPintField: For precise decimal quantities

Form Fields and Widgets

  • Built-in form fields with unit conversion
  • TabledPintFieldWidget for displaying unit conversion tables
  • Customizable validation and unit choices

Form Fields

  • IntegerPintFormField: Used in forms with IntegerPintField.
  • DecimalPintFormField: Used in forms with DecimalPintField.

Widgets

  • PintFieldWidget: Default widget for all django pint field types.
  • TabledPintFieldWidget: Provides a table showing conversion to each of the unit_choices.

TabledPintFieldWidget

Django REST Framework Integration

from django_pint_field.rest import DecimalPintRestField


class ProductSerializer(serializers.ModelSerializer):
    weight = DecimalPintRestField()

    class Meta:
        model = Product
        fields = ["name", "weight"]
The package is tested to work with both Django REST Framework and Django Ninja.

Supported Lookups

  • exact
  • gt, gte
  • lt, lte
  • range
  • isnull

Aggregation Support

from django_pint_field.aggregates import PintAvg, PintSum

Product.objects.aggregate(
    avg_weight=PintAvg("weight"),
    total_weight=PintSum("weight"),
)

Supported Aggregates

  • PintAvg
  • PintCount
  • PintMax
  • PintMin
  • PintSum
  • PintStdDev
  • PintVariance
  • PintPercentile - continuous percentile (PERCENTILE_CONT)
  • PintMedian - 50th percentile
  • pint_histogram() - equi-width histogram helper

Running Totals and Partitioned Aggregates

Use PintWindow for unit-aware window functions; a plain django.db.models.Window around a Pint aggregate is rejected (it cannot carry the unit conversion):

from django.db.models import F
from django_pint_field.aggregates import PintSum, PintWindow

Product.objects.annotate(
    running_total=PintWindow(PintSum("weight"), order_by=F("pk").asc()),
)

The result is a PintFieldProxy in the field's base unit; pass output_unit= on the wrapped aggregate (or call .quantity.to(...)) to convert. Ordered-set aggregates (PintPercentile, PintMedian) cannot be used in a window.

Advanced Usage

Custom Units

Create your own unit registry:

from pint import UnitRegistry

custom_ureg = UnitRegistry(non_int_type=Decimal)
custom_ureg.define("custom_unit = [custom]")

# In settings.py
DJANGO_PINT_FIELD_UNIT_REGISTER = custom_ureg

Indexing

Django Pint Field supports creating indexes on the comparator components of Pint fields. Indexes can improve query performance when filtering, ordering, or joining on Pint field values.

Single Field Index

from django_pint_field.indexes import PintFieldComparatorIndex


class Package(models.Model):
    weight = DecimalPintField("gram")

    class Meta:
        indexes = [PintFieldComparatorIndex(fields=["weight"])]

Multi-Field Index

from django_pint_field.indexes import PintFieldComparatorIndex


class Package(models.Model):
    weight = DecimalPintField("gram")
    volume = DecimalPintField("liter")

    class Meta:
        indexes = [PintFieldComparatorIndex(fields=["weight", "volume"])]

You can also use additional index options, as usual. e.g.:

  • name: Custom index name
  • condition: Partial index condition
  • include: Additional columns to include in the index
  • db_tablespace: Custom tablespace for the index

Settings

# settings.py

# Set decimal precision for the entire project
DJANGO_PINT_FIELD_DECIMAL_PRECISION = 40

# Configure custom unit registry
DJANGO_PINT_FIELD_UNIT_REGISTER = custom_ureg

# Set default format for quantity display
DJANGO_PINT_FIELD_DEFAULT_FORMAT = "D"  # Options: D, P, ~P, etc.

Credits

Modified from django-pint with a focus on composite field storage and enhanced comparison capabilities.

Metadata

Release files for django-pint-field 2026.6.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-pint-field 2026.6.1
File Size Uploaded
django_pint_field-2026.6.1.tar.gz 51.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-pint-field 2026.6.1
File Interpreter ABI Platform
django_pint_field-2026.6.1-py3-none-any.whl Python 3 none any Details

Total release size: 108.9 kB

Release files / django_pint_field-2026.6.1.tar.gz

Download URL django_pint_field-2026.6.1.tar.gz
Size 51.7 kB
Tags Source
SHA-256 checksum
How to use checksums
64d9f7fc4afcd987bb57c982df2d5a891414d291b84af54b8d6e47c4c3f08b3b
BLAKE2b-256 checksum
How to use checksums
0c877da1a66bb70ab336d9bd9bced8cb306589c22fa449c6b55f1771887f54f4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / django_pint_field-2026.6.1-py3-none-any.whl

Download URL django_pint_field-2026.6.1-py3-none-any.whl
Size 57.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c6a4b6dfeee8ee1998d1bf5962d82c2d609c68a7124731f21c3f18968ed0fe5b
BLAKE2b-256 checksum
How to use checksums
09ed7eabe58f5d374be74bc79e01f31aeaee8a04673b89b882ce76dbb4151663
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

2026.6.1 This release

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page