Skip to main content

Unit Conversion fields for Django and Postgres

Project description

django-pint-field

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 Postgres composite field to store both the magnitude and units, along with a base unit 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.10+
  • Django 4.2+
  • PostgreSQL database
  • Pint 0.23+

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 migrations will result in errors for any model making use of django-pint-field.

Quick Start

  1. Define your model:
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",
        max_digits=10,
        decimal_places=2,
        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(340, "gram")
)

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

# Access values
print(product.weight)  # 340 gram
print(product.weight.to("kilogram"))  # 0.34 kilogram

Features

Field Types

  • IntegerPintField: For whole number quantities
  • DecimalPintField: For precise decimal quantities
  • BigIntegerPintField: For large whole number 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 and BigIntegerPintField.
  • 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']

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')
)

Advanced Usage

Custom Units

Create your own unit registry:

from pint import UnitRegistry

custom_ureg = UnitRegistry()
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", max_digits=10, decimal_places=2)

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

Multi-Field Index

from django_pint_field.indexes import PintFieldComparatorIndex

class Package(models.Model):
    weight = DecimalPintField("gram", max_digits=10, decimal_places=2)
    volume = DecimalPintField("liter", max_digits=10, decimal_places=2)

    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

Credits

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_pint_field-2024.11.1.tar.gz (27.0 kB view details)

Uploaded Source

Built Distribution

django_pint_field-2024.11.1-py3-none-any.whl (30.5 kB view details)

Uploaded Python 3

File details

Details for the file django_pint_field-2024.11.1.tar.gz.

File metadata

File hashes

Hashes for django_pint_field-2024.11.1.tar.gz
Algorithm Hash digest
SHA256 2c0ab2bad8be5374056c96c8773d488c7d0ebad44d10c1ec0b61c64f1c3ca9b2
MD5 aef00f3fe7beca452f818d7fe9bbc0b0
BLAKE2b-256 2747394e6dec2d6f24da9735acb675f8196fdaa20542138ec0eae645721d89a0

See more details on using hashes here.

File details

Details for the file django_pint_field-2024.11.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_pint_field-2024.11.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a832b32027a347a3a05e8d1f63fa8dd051c379e6e2d7284b6b3f3374db72ec28
MD5 715910d29e74c5a99d06c08d12c84806
BLAKE2b-256 d6ce97e408030bb1930b9a656399f1ae3048ffb106fd59b7f783d5923e047721

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page