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
- 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"]
)
- 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
.
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 namecondition
: Partial index conditioninclude
: Additional columns to include in the indexdb_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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file django_pint_field-2024.11.2.tar.gz
.
File metadata
- Download URL: django_pint_field-2024.11.2.tar.gz
- Upload date:
- Size: 27.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.4.28
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d444d5a88ca495b0a002df1526c2656b3e762f17d619c363a2689bdb468d5f12 |
|
MD5 | c9462b2ca7d3667ee0982d2fb7e42508 |
|
BLAKE2b-256 | a6fba4fc72764c8a2944444de0778c83b74cab0661ba32701d670b46aa631380 |
File details
Details for the file django_pint_field-2024.11.2-py3-none-any.whl
.
File metadata
- Download URL: django_pint_field-2024.11.2-py3-none-any.whl
- Upload date:
- Size: 30.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.4.28
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 167d378575bff28ffd6e45ba6e1b7a251b1ae15f99d75da0cf77457686052515 |
|
MD5 | 95e9c1feba4b7bf9aedafa7fae72d733 |
|
BLAKE2b-256 | 2c58bcaf7efc579f96335df2786beceeeeaeaee968daab096381ed71d19f4821 |