{"id":16417381,"url":"https://github.com/OmenApps/django-pint-field","last_synced_at":"2025-10-26T20:30:36.160Z","repository":{"id":65149501,"uuid":"583151912","full_name":"OmenApps/django-pint-field","owner":"OmenApps","description":"Store, validate, and convert physical quantities in Django using Pint.","archived":false,"fork":false,"pushed_at":"2025-01-17T15:59:06.000Z","size":3852,"stargazers_count":34,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-06T02:48:33.200Z","etag":null,"topics":["conversion-utility","conversions","django","pint","unit-of-measure","units"],"latest_commit_sha":null,"homepage":"https://django-pint-field.readthedocs.io/en/latest/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OmenApps.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-28T23:26:34.000Z","updated_at":"2025-02-03T21:45:23.000Z","dependencies_parsed_at":"2024-05-05T07:22:12.672Z","dependency_job_id":"0fdccd9f-95ce-4c27-a051-57a21ba1999e","html_url":"https://github.com/OmenApps/django-pint-field","commit_stats":null,"previous_names":["jacklinke/django-pint-field"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OmenApps%2Fdjango-pint-field","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OmenApps%2Fdjango-pint-field/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OmenApps%2Fdjango-pint-field/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OmenApps%2Fdjango-pint-field/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OmenApps","download_url":"https://codeload.github.com/OmenApps/django-pint-field/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238394323,"owners_count":19464583,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["conversion-utility","conversions","django","pint","unit-of-measure","units"],"created_at":"2024-10-11T07:11:28.780Z","updated_at":"2025-10-26T20:30:36.153Z","avatar_url":"https://github.com/OmenApps.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# django-pint-field\n\n[![Published on Django Packages](https://img.shields.io/badge/Published%20on-Django%20Packages-0c3c26)](https://djangopackages.org/packages/p/django-pint-field/)\n[![PyPI](https://img.shields.io/pypi/v/django-pint-field)](https://pypi.org/project/django-pint-field/)\n\nStore, validate, and convert physical quantities in Django using [Pint](https://pint.readthedocs.io/en/stable/).\n\n## Why Django Pint Field?\n\nDjango Pint Field enables you to:\n\n- Store quantities (like 1 gram, 3 miles, 8.120391 angstroms) in your Django models\n- Edit quantities in forms with automatic unit conversion\n- Compare quantities in different units (e.g., compare weights in pounds vs. kilograms)\n- Display quantities in user-preferred units while maintaining accurate comparisons\n- Perform aggregations and lookups across different units of measurement\n\nThe 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.\n\n## Requirements\n\n- Python 3.11+\n- Django 4.2+\n- PostgreSQL database\n- Pint 0.23+\n\n## Installation\n\n```bash\npip install django-pint-field\n```\n\nAdd to your `INSTALLED_APPS`:\n\n```python\nINSTALLED_APPS = [\n    # ...\n    \"django_pint_field\",\n    # ...\n]\n```\n\nRun migrations:\n\n```bash\npython manage.py migrate django_pint_field\n```\n\n```{caution}\nFailure 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.\n\nPrevious 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.\n```\n\n### Tips for Upgrading from Legacy django-pint-field\n\n```{warning}\nIf 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.\n```\n\n```bash\npython manage.py pgtrigger uninstall\n```\n\nThen run the migrations:\n\n```bash\npython manage.py migrate django_pint_field\n```\n\nReinstall the triggers after the migrations are complete:\n\n```bash\npython manage.py pgtrigger install\n```\n\n## Quick Start\n\n1. Define your model:\n\n```python\nfrom decimal import Decimal\nfrom django.db import models\nfrom django_pint_field.models import DecimalPintField\n\n\nclass Product(models.Model):\n    name = models.CharField(max_length=Decimal(\"100\"))\n    weight = DecimalPintField(\n        default_unit=\"gram\",\n        unit_choices=[\"gram\", \"kilogram\", \"pound\", \"ounce\"],\n    )\n```\n\n2. Use it in your code:\n\n```python\nfrom django_pint_field.units import ureg\n\n# Create objects\nproduct = Product.objects.create(\n    name=\"Coffee Bag\",\n    weight=ureg.Quantity(Decimal(\"340\"), \"gram\"),\n)\n\n# Query using different units\nproducts = Product.objects.filter(\n    weight__gte=ureg.Quantity(Decimal(\"0.5\"), \"kilogram\"),\n)\n\n# Access values\nprint(product.weight)  # 3460 gram\nprint(product.weight.quantity)  # 3460 gram (accessing the Pint Quantity object)\n# Convert to different units\nprint(product.weight.quantity.to(\"kilogram\"))  # 0.346 kilogram\nprint(product.weight.kilogram)  # 0.346 kilogram\nprint(product.weight.kilogram__2)  # 0.35 kilogram  (rounded to 2 decimal places)\n```\n\n## Features\n\n### Field Types\n\n- **IntegerPintField**: For whole number quantities\n- **DecimalPintField**: For precise decimal quantities\n- **BigIntegerPintField**: For large whole number quantities (deprecated, use IntegerPintField instead)\n\n### Form Fields and Widgets\n\n- Built-in form fields with unit conversion\n- TabledPintFieldWidget for displaying unit conversion tables\n- Customizable validation and unit choices\n\n#### Form Fields\n\n- **IntegerPintFormField**: Used in forms with IntegerPintField and BigIntegerPintField.\n- **DecimalPintFormField**: Used in forms with DecimalPintField.\n\n#### Widgets\n\n- **PintFieldWidget**: Default widget for all django pint field types.\n- **TabledPintFieldWidget**: Provides a table showing conversion to each of the `unit_choices`.\n\n![TabledPintFieldWidget](https://raw.githubusercontent.com/jacklinke/django-pint-field/main/media/TabledPintFieldWidget.png)\n\n### Django REST Framework Integration\n\n```python\nfrom django_pint_field.rest import DecimalPintRestField\n\n\nclass ProductSerializer(serializers.ModelSerializer):\n    weight = DecimalPintRestField()\n\n    class Meta:\n        model = Product\n        fields = [\"name\", \"weight\"]\n```\n\n```{note}\nThe package is tested to work with both Django REST Framework and Django Ninja.\n```\n\n### Supported Lookups\n\n- `exact`\n- `gt`, `gte`\n- `lt`, `lte`\n- `range`\n- `isnull`\n\n### Aggregation Support\n\n```python\nfrom django_pint_field.aggregates import PintAvg, PintSum\n\nProduct.objects.aggregate(\n    avg_weight=PintAvg(\"weight\"),\n    total_weight=PintSum(\"weight\"),\n)\n```\n\n#### Supported Aggregates\n\n- `PintAvg`\n- `PintCount`\n- `PintMax`\n- `PintMin`\n- `PintSum`\n- `PintStdDev`\n- `PintVariance`\n\n## Advanced Usage\n\n### Custom Units\n\nCreate your own unit registry:\n\n```python\nfrom pint import UnitRegistry\n\ncustom_ureg = UnitRegistry(non_int_type=Decimal)\ncustom_ureg.define(\"custom_unit = [custom]\")\n\n# In settings.py\nDJANGO_PINT_FIELD_UNIT_REGISTER = custom_ureg\n```\n\n### Indexing\n\nDjango 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.\n\n#### Single Field Index\n\n```python\nfrom django_pint_field.indexes import PintFieldComparatorIndex\n\n\nclass Package(models.Model):\n    weight = DecimalPintField(\"gram\")\n\n    class Meta:\n        indexes = [PintFieldComparatorIndex(fields=[\"weight\"])]\n```\n\n#### Multi-Field Index\n\n```python\nfrom django_pint_field.indexes import PintFieldComparatorIndex\n\n\nclass Package(models.Model):\n    weight = DecimalPintField(\"gram\")\n    volume = DecimalPintField(\"liter\")\n\n    class Meta:\n        indexes = [PintFieldComparatorIndex(fields=[\"weight\", \"volume\"])]\n```\n\nYou can also use additional index options, as usual. e.g.:\n\n- `name`: Custom index name\n- `condition`: Partial index condition\n- `include`: Additional columns to include in the index\n- `db_tablespace`: Custom tablespace for the index\n\n### Settings\n\n```python\n# settings.py\n\n# Set decimal precision for the entire project\nDJANGO_PINT_FIELD_DECIMAL_PRECISION = 40\n\n# Configure custom unit registry\nDJANGO_PINT_FIELD_UNIT_REGISTER = custom_ureg\n\n# Set default format for quantity display\nDJANGO_PINT_FIELD_DEFAULT_FORMAT = \"D\"  # Options: D, P, ~P, etc.\n```\n\n## Credits\n\nModified from [django-pint](https://github.com/CarliJoy/django-pint) with a focus on composite field storage and enhanced comparison capabilities.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOmenApps%2Fdjango-pint-field","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FOmenApps%2Fdjango-pint-field","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOmenApps%2Fdjango-pint-field/lists"}