django-pint-field


Namedjango-pint-field JSON
Version 0.3.5 PyPI version JSON
download
home_pagehttps://github.com/jacklinke/django-pint-field
SummaryPint Fields for Django and Postgres
upload_time2023-01-28 21:29:35
maintainer
docs_urlNone
authorJack Linke
requires_python>=3.8,<4.0
licenseMIT
keywords django
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
# django-pint-field

Use [pint](https://pint.readthedocs.io/en/stable/) with Django's ORM.

If you want to store quantities (1 gram, 3 miles, 8.120391 angstroms, etc) in a model, edit them in forms, and have the ability to convert to other quantities in your django projects, this is the package for you!

This package is modified from the fantastic [django-pint](https://github.com/CarliJoy/django-pint) with different goals. Unlike django-pint, in this project we use a composite Postgres field to store both the magnitude and the user's desired units, along with the equivalent value in base units. This third piece of date - the base units - makes it possible to conduct lookups comparing one instance that might be specified in "grams" with another that may be specified in "pounds", but display each instance in the units that the user desires. The units your users want to use are the units they see, while still allowing accurate comparisons of one quantity to another.

For this reason, the project only works with Postgresql databases.


## Install

`pip install django_pint_field`

Add `"django_pint_field",` to your list of installed apps.

Run `python manage.py migrate django_pint_field`


## Usage

Assuming we are starting with the following model:

```python
from decimal import Decimal
from django.db import models
from django.db.models import DecimalField

from django_pint_field.models import IntegerPintField


class IntegerPintFieldSaveModel(models.Model):
    name = models.CharField(max_length=20)
    weight = IntegerPintField("gram")

    def __str__(self):
        return str(self.name)
```

We can do the following:

```python
from decimal import Decimal
from django_pint_field.units import ureg

from .models import IntegerPintFieldSaveModel

Quantity = ureg.Quantity

# Start by creating a few Pint Quantity objects
extra_small = Quantity(1 * ureg.gram)
small = Quantity(10 * ureg.gram)
medium = Quantity(100 * ureg.gram)
large = Quantity(1000 * ureg.gram)
extra_large = Quantity(10000 * ureg.gram)

# Create a couple objects
IntegerPintFieldSaveModel.objects.create(name="small", weight=small)
IntegerPintFieldSaveModel.objects.create(name="large", weight=large)

In [1]: IntegerPintFieldSaveModel.objects.first()
Out[1]: <IntegerPintFieldSaveModel: small>

In [2]: IntegerPintFieldSaveModel.objects.first().weight
Out[2]: 10 <Unit('gram')>

In [3]: IntegerPintFieldSaveModel.objects.first().weight.magnitude
Out[3]: 10

In [4]: IntegerPintFieldSaveModel.objects.first().weight.units
Out[4]: <Unit('gram')>
```


## Valid Lookups

Other lookups will be added in the future. Currently available are:

- exact
- gt
- gte
- lt
- lte
- range
- isnull

```python
# Perform some queries
IntegerPintFieldSaveModel.objects.filter(weight__gt=medium)
<QuerySet [<IntegerPintFieldSaveModel: large>]>

IntegerPintFieldSaveModel.objects.filter(weight__gt=extra_small)
<QuerySet [<IntegerPintFieldSaveModel: small>, <IntegerPintFieldSaveModel: large>]>

IntegerPintFieldSaveModel.objects.filter(weight__gte=small)
<QuerySet [<IntegerPintFieldSaveModel: small>, <IntegerPintFieldSaveModel: large>]>

IntegerPintFieldSaveModel.objects.filter(weight__range=(small, medium))
<QuerySet [<IntegerPintFieldSaveModel: small>]>
```


## Aggregates

A number of aggregates have been implemented for the Django Pint Fields. Functionally they perform for Pint Fields the same way django's default aggregates work for other field types, and each is prepended with "Pint". The aggregates include:

- PintAvg
- PintCount
- PintMax
- PintMin
- PintStdDev
- PintSum
- PintVariance

```python
from django_pint_field.aggregates import PintAvg, PintCount, PintMax, PintMin, PintStdDev, PintSum, PintVariance

# Perform some queries
IntegerPintFieldSaveModel.objects.aggregate(PintAvg('weight'))
{'weight__pintavg': Decimal('0.50500000000000000000') <Unit('kilogram')>}

IntegerPintFieldSaveModel.objects.aggregate(PintCount('weight'))
{'weight__pintcount': 2}

IntegerPintFieldSaveModel.objects.aggregate(PintMax('weight'))
{'weight__pintmax': Decimal('1.0') <Unit('kilogram')>}

IntegerPintFieldSaveModel.objects.aggregate(PintMin('weight'))
{'weight__pintmin': Decimal('0.01') <Unit('kilogram')>}

IntegerPintFieldSaveModel.objects.aggregate(PintStdDev('weight'))
{'weight__pintstddev': Decimal('0.49500000000000000000') <Unit('kilogram')>}

IntegerPintFieldSaveModel.objects.aggregate(PintSum('weight'))
{'weight__pintsum': Decimal('1.01') <Unit('kilogram')>}

IntegerPintFieldSaveModel.objects.aggregate(PintVariance('weight'))
{'weight__pintvariance': Decimal('0.24502500000000000000') <Unit('kilogram')>}
```


## Use with Django Rest Framework


```python
from django_pint_field.rest import IntegerPintRestField

class DjangoPintFieldSerializer(serializers.ModelSerializer):
    # Let DRF know which type of serializer field to use
    weight = IntegerPintRestField()

    class Meta:
        model = IntegerPintFieldSaveModel
        fields = ["name", "weight"]
```


## Creating your own units

You can [create your own pint units](https://pint.readthedocs.io/en/stable/advanced/defining.html) if the [default units](https://github.com/hgrecco/pint/blob/master/pint/default_en.txt) in pint are not sufficient.

Anywhere within your project (ideally in settings or a file adjacent to settings), define the custom unit registry by importing Pint's default UnitRegistry and extending it:

```python
from pint import UnitRegistry

custom_ureg = UnitRegistry()
custom_ureg.define("custom = [custom]")
custom_ureg.define("kilocustom = 1000 * custom")
```

Then add the custom registry to your app's settings.py:

`DJANGO_PINT_FIELD_UNIT_REGISTER = custom_ureg`


## Model Fields

- **IntegerPintField**: Stores a pint measurement as an integer (-2147483648 to 2147483647).
- **BigIntegerPintField**: Stores a pint measurement as a big integer (-9223372036854775808 to 9223372036854775807).
- **DecimalPintField**: Stores a pint measurement as a decimal. Like Django's DecimalField, DecimalPintField takes required `max_digits` and `decimal_places` parameters.


## 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](https://raw.githubusercontent.com/jacklinke/django-pint-field/main/media/TabledPintFieldWidget.png)


Example usage:

```python
class WeightModel(models.Model):
    decimal_weight = DecimalPintField(
        "gram",
        blank=True,
        null=True,
        max_digits=10,
        decimal_places=2,
        unit_choices=[
            "kilogram",
            "milligram",
            "pounds"
        ],
    )

class TabledWeightForm(forms.ModelForm):
    class Meta:
        model = WeightModel
        fields = "__all__"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # If we want to use the tabled widget, we need to pass the 
        #   default_unit and unit_choices to the new widget
        default_unit = self.fields["decimal_weight"].default_unit
        unit_choices = self.fields["decimal_weight"].unit_choices
        self.fields["decimal_weight"].widget = TabledPintFieldWidget(
            default_unit=default_unit, unit_choices=unit_choices
        )
```

The template for this widget is located at https://github.com/jacklinke/django-pint-field/blob/main/django_pint_field/templates/tabled_django_pint_field_widget.html

If you want to override the template, add your own template in your project at: "templates/django_pint_field/tabled_django_pint_field_widget.html"

## DRF Serializer Fields

- **IntegerPintRestField**: Used in DRF with IntegerPintField and BigIntegerPintField.
- **DecimalPintRestField**: Used in DRF with DecimalPintField.


## Settings

<dl>
  <dt><code>DJANGO_PINT_FIELD_DECIMAL_PRECISION</code></dt>
  <dd>
    Determines whether django_pint_field should automatically set the python decimal precision for the project. If an integer greater than 0 is provided, the decimal context precision for the entire project will be set to that value. Otherwise, the precision remains at the default (usually 28).<br>
    <em>* Type: int</em>
    <em>* Default: 0</em>
  </dd>

  <dt><code>DJANGO_PINT_FIELD_UNIT_REGISTER</code></dt>
  <dd>
    The Unit Registry to use in the project. Defaults to pint.UnitRegistry.<br>
    <em>* Type: int</em>
    <em>* Default: 0</em>
  </dd>
</dl>


## Rounding modes (upcoming feature)

**decimal.ROUND_CEILING**
Round towards Infinity.

**decimal.ROUND_DOWN**
Round towards zero.

**decimal.ROUND_FLOOR**
Round towards -Infinity.

**decimal.ROUND_HALF_DOWN**
Round to nearest with ties going towards zero.

**decimal.ROUND_HALF_EVEN**
Round to nearest with ties going to nearest even integer.

**decimal.ROUND_HALF_UP**
Round to nearest with ties going away from zero.

**decimal.ROUND_UP**
Round away from zero.

**decimal.ROUND_05UP**
Round away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise round towards zero.

Read more about rounding modes for decimals at the [decimal docs](https://docs.python.org/3/library/decimal.html#rounding-modes)


## Use the test app with docker compose

### Set up a virtual environment (recommended)

Make a virtual environment named `.venv`:

`python3 -m venv .venv`
    
Activate the new environment:

`source .venv/bin/activate`


### Install dependencies

*Requires [poetry](https://python-poetry.org/). If you do not yet have it installed, run `pip install poetry`.*

`poetry install --with dev`

### Build and bring up

```
docker compose build
docker compose run django python manage.py migrate
docker compose run django python manage.py createsuperuser
docker compose up -d
```

Navigate to `127.0.0.1:8000`

### Test (assuming you have already performed `build`)

`docker compose run django python manage.py test`


## Run psql on the Postgres database

`docker compose exec postgres psql -U postgres`


## ToDos:
- Implement rounding modes
- Think through what it would take to build range types for these fields
- Add extensible widget template

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/jacklinke/django-pint-field",
    "name": "django-pint-field",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<4.0",
    "maintainer_email": "",
    "keywords": "django",
    "author": "Jack Linke",
    "author_email": "jack@watervize.com",
    "download_url": "https://files.pythonhosted.org/packages/1a/6a/6e9b1835b81e77eb36036515d1e6caaa45b91744e8e00281117d7bcfbe04/django_pint_field-0.3.5.tar.gz",
    "platform": null,
    "description": "\n# django-pint-field\n\nUse [pint](https://pint.readthedocs.io/en/stable/) with Django's ORM.\n\nIf you want to store quantities (1 gram, 3 miles, 8.120391 angstroms, etc) in a model, edit them in forms, and have the ability to convert to other quantities in your django projects, this is the package for you!\n\nThis package is modified from the fantastic [django-pint](https://github.com/CarliJoy/django-pint) with different goals. Unlike django-pint, in this project we use a composite Postgres field to store both the magnitude and the user's desired units, along with the equivalent value in base units. This third piece of date - the base units - makes it possible to conduct lookups comparing one instance that might be specified in \"grams\" with another that may be specified in \"pounds\", but display each instance in the units that the user desires. The units your users want to use are the units they see, while still allowing accurate comparisons of one quantity to another.\n\nFor this reason, the project only works with Postgresql databases.\n\n\n## Install\n\n`pip install django_pint_field`\n\nAdd `\"django_pint_field\",` to your list of installed apps.\n\nRun `python manage.py migrate django_pint_field`\n\n\n## Usage\n\nAssuming we are starting with the following model:\n\n```python\nfrom decimal import Decimal\nfrom django.db import models\nfrom django.db.models import DecimalField\n\nfrom django_pint_field.models import IntegerPintField\n\n\nclass IntegerPintFieldSaveModel(models.Model):\n    name = models.CharField(max_length=20)\n    weight = IntegerPintField(\"gram\")\n\n    def __str__(self):\n        return str(self.name)\n```\n\nWe can do the following:\n\n```python\nfrom decimal import Decimal\nfrom django_pint_field.units import ureg\n\nfrom .models import IntegerPintFieldSaveModel\n\nQuantity = ureg.Quantity\n\n# Start by creating a few Pint Quantity objects\nextra_small = Quantity(1 * ureg.gram)\nsmall = Quantity(10 * ureg.gram)\nmedium = Quantity(100 * ureg.gram)\nlarge = Quantity(1000 * ureg.gram)\nextra_large = Quantity(10000 * ureg.gram)\n\n# Create a couple objects\nIntegerPintFieldSaveModel.objects.create(name=\"small\", weight=small)\nIntegerPintFieldSaveModel.objects.create(name=\"large\", weight=large)\n\nIn [1]: IntegerPintFieldSaveModel.objects.first()\nOut[1]: <IntegerPintFieldSaveModel: small>\n\nIn [2]: IntegerPintFieldSaveModel.objects.first().weight\nOut[2]: 10 <Unit('gram')>\n\nIn [3]: IntegerPintFieldSaveModel.objects.first().weight.magnitude\nOut[3]: 10\n\nIn [4]: IntegerPintFieldSaveModel.objects.first().weight.units\nOut[4]: <Unit('gram')>\n```\n\n\n## Valid Lookups\n\nOther lookups will be added in the future. Currently available are:\n\n- exact\n- gt\n- gte\n- lt\n- lte\n- range\n- isnull\n\n```python\n# Perform some queries\nIntegerPintFieldSaveModel.objects.filter(weight__gt=medium)\n<QuerySet [<IntegerPintFieldSaveModel: large>]>\n\nIntegerPintFieldSaveModel.objects.filter(weight__gt=extra_small)\n<QuerySet [<IntegerPintFieldSaveModel: small>, <IntegerPintFieldSaveModel: large>]>\n\nIntegerPintFieldSaveModel.objects.filter(weight__gte=small)\n<QuerySet [<IntegerPintFieldSaveModel: small>, <IntegerPintFieldSaveModel: large>]>\n\nIntegerPintFieldSaveModel.objects.filter(weight__range=(small, medium))\n<QuerySet [<IntegerPintFieldSaveModel: small>]>\n```\n\n\n## Aggregates\n\nA number of aggregates have been implemented for the Django Pint Fields. Functionally they perform for Pint Fields the same way django's default aggregates work for other field types, and each is prepended with \"Pint\". The aggregates include:\n\n- PintAvg\n- PintCount\n- PintMax\n- PintMin\n- PintStdDev\n- PintSum\n- PintVariance\n\n```python\nfrom django_pint_field.aggregates import PintAvg, PintCount, PintMax, PintMin, PintStdDev, PintSum, PintVariance\n\n# Perform some queries\nIntegerPintFieldSaveModel.objects.aggregate(PintAvg('weight'))\n{'weight__pintavg': Decimal('0.50500000000000000000') <Unit('kilogram')>}\n\nIntegerPintFieldSaveModel.objects.aggregate(PintCount('weight'))\n{'weight__pintcount': 2}\n\nIntegerPintFieldSaveModel.objects.aggregate(PintMax('weight'))\n{'weight__pintmax': Decimal('1.0') <Unit('kilogram')>}\n\nIntegerPintFieldSaveModel.objects.aggregate(PintMin('weight'))\n{'weight__pintmin': Decimal('0.01') <Unit('kilogram')>}\n\nIntegerPintFieldSaveModel.objects.aggregate(PintStdDev('weight'))\n{'weight__pintstddev': Decimal('0.49500000000000000000') <Unit('kilogram')>}\n\nIntegerPintFieldSaveModel.objects.aggregate(PintSum('weight'))\n{'weight__pintsum': Decimal('1.01') <Unit('kilogram')>}\n\nIntegerPintFieldSaveModel.objects.aggregate(PintVariance('weight'))\n{'weight__pintvariance': Decimal('0.24502500000000000000') <Unit('kilogram')>}\n```\n\n\n## Use with Django Rest Framework\n\n\n```python\nfrom django_pint_field.rest import IntegerPintRestField\n\nclass DjangoPintFieldSerializer(serializers.ModelSerializer):\n    # Let DRF know which type of serializer field to use\n    weight = IntegerPintRestField()\n\n    class Meta:\n        model = IntegerPintFieldSaveModel\n        fields = [\"name\", \"weight\"]\n```\n\n\n## Creating your own units\n\nYou can [create your own pint units](https://pint.readthedocs.io/en/stable/advanced/defining.html) if the [default units](https://github.com/hgrecco/pint/blob/master/pint/default_en.txt) in pint are not sufficient.\n\nAnywhere within your project (ideally in settings or a file adjacent to settings), define the custom unit registry by importing Pint's default UnitRegistry and extending it:\n\n```python\nfrom pint import UnitRegistry\n\ncustom_ureg = UnitRegistry()\ncustom_ureg.define(\"custom = [custom]\")\ncustom_ureg.define(\"kilocustom = 1000 * custom\")\n```\n\nThen add the custom registry to your app's settings.py:\n\n`DJANGO_PINT_FIELD_UNIT_REGISTER = custom_ureg`\n\n\n## Model Fields\n\n- **IntegerPintField**: Stores a pint measurement as an integer (-2147483648 to 2147483647).\n- **BigIntegerPintField**: Stores a pint measurement as a big integer (-9223372036854775808 to 9223372036854775807).\n- **DecimalPintField**: Stores a pint measurement as a decimal. Like Django's DecimalField, DecimalPintField takes required `max_digits` and `decimal_places` parameters.\n\n\n## Form Fields\n\n- **IntegerPintFormField**: Used in forms with IntegerPintField and BigIntegerPintField.\n- **DecimalPintFormField**: Used in forms with DecimalPintField.\n\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\nExample usage:\n\n```python\nclass WeightModel(models.Model):\n    decimal_weight = DecimalPintField(\n        \"gram\",\n        blank=True,\n        null=True,\n        max_digits=10,\n        decimal_places=2,\n        unit_choices=[\n            \"kilogram\",\n            \"milligram\",\n            \"pounds\"\n        ],\n    )\n\nclass TabledWeightForm(forms.ModelForm):\n    class Meta:\n        model = WeightModel\n        fields = \"__all__\"\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n        # If we want to use the tabled widget, we need to pass the \n        #   default_unit and unit_choices to the new widget\n        default_unit = self.fields[\"decimal_weight\"].default_unit\n        unit_choices = self.fields[\"decimal_weight\"].unit_choices\n        self.fields[\"decimal_weight\"].widget = TabledPintFieldWidget(\n            default_unit=default_unit, unit_choices=unit_choices\n        )\n```\n\nThe template for this widget is located at https://github.com/jacklinke/django-pint-field/blob/main/django_pint_field/templates/tabled_django_pint_field_widget.html\n\nIf you want to override the template, add your own template in your project at: \"templates/django_pint_field/tabled_django_pint_field_widget.html\"\n\n## DRF Serializer Fields\n\n- **IntegerPintRestField**: Used in DRF with IntegerPintField and BigIntegerPintField.\n- **DecimalPintRestField**: Used in DRF with DecimalPintField.\n\n\n## Settings\n\n<dl>\n  <dt><code>DJANGO_PINT_FIELD_DECIMAL_PRECISION</code></dt>\n  <dd>\n    Determines whether django_pint_field should automatically set the python decimal precision for the project. If an integer greater than 0 is provided, the decimal context precision for the entire project will be set to that value. Otherwise, the precision remains at the default (usually 28).<br>\n    <em>* Type: int</em>\n    <em>* Default: 0</em>\n  </dd>\n\n  <dt><code>DJANGO_PINT_FIELD_UNIT_REGISTER</code></dt>\n  <dd>\n    The Unit Registry to use in the project. Defaults to pint.UnitRegistry.<br>\n    <em>* Type: int</em>\n    <em>* Default: 0</em>\n  </dd>\n</dl>\n\n\n## Rounding modes (upcoming feature)\n\n**decimal.ROUND_CEILING**\nRound towards Infinity.\n\n**decimal.ROUND_DOWN**\nRound towards zero.\n\n**decimal.ROUND_FLOOR**\nRound towards -Infinity.\n\n**decimal.ROUND_HALF_DOWN**\nRound to nearest with ties going towards zero.\n\n**decimal.ROUND_HALF_EVEN**\nRound to nearest with ties going to nearest even integer.\n\n**decimal.ROUND_HALF_UP**\nRound to nearest with ties going away from zero.\n\n**decimal.ROUND_UP**\nRound away from zero.\n\n**decimal.ROUND_05UP**\nRound away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise round towards zero.\n\nRead more about rounding modes for decimals at the [decimal docs](https://docs.python.org/3/library/decimal.html#rounding-modes)\n\n\n## Use the test app with docker compose\n\n### Set up a virtual environment (recommended)\n\nMake a virtual environment named `.venv`:\n\n`python3 -m venv .venv`\n    \nActivate the new environment:\n\n`source .venv/bin/activate`\n\n\n### Install dependencies\n\n*Requires [poetry](https://python-poetry.org/). If you do not yet have it installed, run `pip install poetry`.*\n\n`poetry install --with dev`\n\n### Build and bring up\n\n```\ndocker compose build\ndocker compose run django python manage.py migrate\ndocker compose run django python manage.py createsuperuser\ndocker compose up -d\n```\n\nNavigate to `127.0.0.1:8000`\n\n### Test (assuming you have already performed `build`)\n\n`docker compose run django python manage.py test`\n\n\n## Run psql on the Postgres database\n\n`docker compose exec postgres psql -U postgres`\n\n\n## ToDos:\n- Implement rounding modes\n- Think through what it would take to build range types for these fields\n- Add extensible widget template\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Pint Fields for Django and Postgres",
    "version": "0.3.5",
    "project_urls": {
        "Homepage": "https://github.com/jacklinke/django-pint-field",
        "Repository": "https://github.com/jacklinke/django-pint-field"
    },
    "split_keywords": [
        "django"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b23740aad90baf243eb09cf42f39c8e4cdb40d18dc5942480f57b8609b7d696a",
                "md5": "2689bf3fc8060fc1999aa36f8ac189b3",
                "sha256": "23c38d343e2e144041179f6dacfb034414514047a3233902dafc48328f42094b"
            },
            "downloads": -1,
            "filename": "django_pint_field-0.3.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "2689bf3fc8060fc1999aa36f8ac189b3",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<4.0",
            "size": 21185,
            "upload_time": "2023-01-28T21:29:33",
            "upload_time_iso_8601": "2023-01-28T21:29:33.212944Z",
            "url": "https://files.pythonhosted.org/packages/b2/37/40aad90baf243eb09cf42f39c8e4cdb40d18dc5942480f57b8609b7d696a/django_pint_field-0.3.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1a6a6e9b1835b81e77eb36036515d1e6caaa45b91744e8e00281117d7bcfbe04",
                "md5": "51f6c7d0474cb435f865f9b1b56c653f",
                "sha256": "1eb2bb18a42c4e2d1b2695059ab8519cdb5fe1e5b10be9ad41b77d6b3078e08e"
            },
            "downloads": -1,
            "filename": "django_pint_field-0.3.5.tar.gz",
            "has_sig": false,
            "md5_digest": "51f6c7d0474cb435f865f9b1b56c653f",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4.0",
            "size": 21215,
            "upload_time": "2023-01-28T21:29:35",
            "upload_time_iso_8601": "2023-01-28T21:29:35.403457Z",
            "url": "https://files.pythonhosted.org/packages/1a/6a/6e9b1835b81e77eb36036515d1e6caaa45b91744e8e00281117d7bcfbe04/django_pint_field-0.3.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-01-28 21:29:35",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jacklinke",
    "github_project": "django-pint-field",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "django-pint-field"
}
        
Elapsed time: 0.28361s