django-fashion-size
Django fields for fashion-size.
SizeTypeField stores which size type a column is (dress, adult-shoe). Reading it returns a SizeType.
SizeUnitField stores which size unit a column is (uk-dress-size). Reading it returns a SizeUnit.
SizeField stores the size token (10, 7.5, DD, MD). Pass size_unit_field pointing at a SizeUnitField on this model or a related one ("size_unit", "attribute.size_unit"). Reading it returns a Size; call .convert() on that value.
The source repository is github.com/ababic/django-fashion-size. It depends on fashion-size (CalVer releases on PyPI).
pip install django-fashion-size
Supported Django versions are 6.0 and 6.1 (see django>=6.0,<7 in pyproject.toml). CI runs the test suite against each of those releases and against Django's main branch.
pip install tox
tox
To run a single environment, for example Django 6.0: tox -e py312-django60.
Frontend sources live under frontend/. Lint and build with cd frontend && npm ci && npm run lint && npm run build (then commit any changes under src/django_fashion_size/static/django_fashion_size/). CI runs Ruff in lint.yml and lint/build checks in frontend.yml.
A release is a vX.Y.Z tag matching the version in pyproject.toml. The release workflow publishes that tag only when the tagged commit is on main or a release-* branch. Building the package compiles the size field's CSS and JavaScript from frontend/ into the static files the widget serves. That compile step runs in the release workflow, and it needs Node.js when you build from this repository. An install from PyPI uses the compiled files and does not need Node.
from django.db import models
from django_fashion_size.model_fields import SizeField, SizeUnitField
class Attribute(models.Model):
size_unit = SizeUnitField()
class AttributeValue(models.Model):
attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE)
size = SizeField(size_unit_field="attribute.size_unit")
value = attribute_value.size
from fashion_size.demographics import Demographic
value.convert_to_locale(
"eu",
demographic=Demographic(age_group="adult", gender="female"),
)
FashionProductType is a Django TextChoices enum with the same values as fashion_size.product_types.ProductType. Its labels are marked for translation (gettext_lazy), so makemessages can collect them.
FashionProductTypeField stores a product-type slug (shoes). Reading it returns a fashion_size.product_types.ProductType, or None when the value is blank or not a known product type. full_clean rejects values that are not in FashionProductType.values. Its default form field is FashionProductTypeFormField, a select whose options always come from FashionProductType. Passed choices are ignored so the list cannot go stale against fashion-size.
SizeTypeSlug and SizeUnitSlug are Django TextChoices enums. Their values match fashion-size (dress, uk-dress-size). Their labels are gettext_lazy strings (Dress size, UK Dress size), so makemessages can collect them. SizeTypeField and SizeUnitField selects always use those labels, in the active language. Passed choices are ignored so a stale list cannot replace them. SizeTypeField stores one of the size-type slugs and returns the SizeType. A blank column reads as None. Use it when the attribute is the size type, and each value keeps its own source unit and raw token:
class Attribute(models.Model):
size_type = SizeTypeField()
class AttributeValue(models.Model):
attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE)
size_unit = SizeUnitField()
size = SizeField(size_unit_field="size_unit")
attribute.size_type is a SizeType (dress). attribute_value.size is a Size in whatever unit was supplied (eu-dress-size / 38). Convert from that pair when a UK token is needed; the stored columns stay the source unit and the raw token.
Importing this package registers Django's get_language as the fashion-size display language and makes Size.display() use it. English lengths render as 32" and 81cm; other languages render as 32 in and 81 cm. fashion-size uses that same formatting for UK, US, and AU waist and chest sizes, and for UK, US, and EU band sizes. EU waist and chest labels, AU bands, and French bands keep their region prefix (EU 46). UK 10 and DD stay the same in every language. Cup size also accepts sports-bra alpha labels (XXS, XS, S, MD, LG, XL, XXL). They convert as the same token in every region, and the autocomplete lists them after the letter chart. Size.display() shows MD and LG as M and L; the stored token stays MD and LG. Brand charts ship with fashion-size; pass brand_name and product_type on Size.convert / Size.convert_to_locale. The model fields do not need this package in INSTALLED_APPS.
SizeField's form control is an autocomplete. You type a size and the list shows chart values that start with that text. A short select beside the field chooses the region or unit you are typing (UK, EU, in, cm). A "View conversion chart" link to the right of the field opens the conversion chart. The value saved on the model is the token in size_unit_field (10 when the field stores UK dress sizes, even if you typed EU 38). Add django_fashion_size to INSTALLED_APPS so the widget's CSS and script are found.
Length size types (chest, waist, inside-leg, shorts-inseam, trousers-inseam, collar, sleeve) convert between inches and centimetres inside that type's own bounds. Shorts inseam is 2–22 inches, trousers inseam is 24–42, and sleeve is 28–40. The autocomplete uses those bounds.
Label size types (trouser-length, top-length, shoe-width, proportion, age-months, age-years, letter) have one universal unit and no conversion chart. The autocomplete lists the vocabulary (Regular, One size). Age bands have no fixed list: type 6 months or 2-3 years and the stored token is the canonical band (6, 2-3). Aliases such as R and small are stored as regular and S.
The same control is SizeFormField, so a CharField such as AttributeValue.value can use it without becoming a SizeField. Pass the attribute's SizeUnit and the brand and product type you already have. brand_name is the brand's name. product_type_name is the product type's name (Shoes) or slug (shoes). Age group and gender select the chart.
self.fields["value"] = SizeFormField(
size_unit=attribute.size_unit,
brand_name=brand_name,
product_type_name=product_type_name,
age_group="adult",
gender="female",
)
Leave those values unset to read them from other fields. A SizeField still passes its size_unit_field. brand_name_field defaults to brand, and product_type_name_field defaults to product_type. Point them at other names when the form uses those:
value = SizeFormField(
size_unit_field="size_unit",
brand_name_field="brand_name",
product_type_name_field="product_type_name",
)
Size description API
fashion_size.descriptions can read a feed string and join sizes back into one. Two POST endpoints expose that to JavaScript and other non-Python clients. They are not mounted until you include them:
path("", include("django_fashion_size.urls"))
POST /size-description-decode/ and POST /size-description-encode/ each accept a JSON object. The caller must have an active authenticated session, and the request must include the CSRF token. source_region is read once for the whole request (uk, eu, us, au, or fr; eur is accepted as eu). items is a list of at most 500 objects. A bad item is reported in results and does not reject the rest of the batch. A bad source_region, a bad preferred_regions list, or more than 500 items rejects the request.
preferred_regions is also request-level. On decode, each size gains a regions list with that size converted into each preferred region. On encode, chart sizes are converted to the first preferred region before the string is built, and each used size includes the same regions list. Lengths move between inches and centimetres (EU and FR use centimetres). Label sizes keep their token and change wording. Chart conversion needs age_group and gender (adult / child / baby, and female / male / unisex), on the request or on the item. Pass brand_name as well when a brand chart should be used; a product type on its own stays on the default chart, because fashion-size requires a brand name alongside a product type.
{
"source_region": "uk",
"preferred_regions": ["eu", "us"],
"age_group": "adult",
"gender": "female",
"items": [
{"value": "UK 10", "product_type": "dresses"}
]
}
Encode items send sizes instead of value:
{
"source_region": "uk",
"preferred_regions": ["eu"],
"age_group": "adult",
"gender": "female",
"items": [
{
"product_type": "dresses",
"sizes": [{"raw": "10", "size_unit": "uk-dress-size"}]
}
]
}
The encoded text for that item is EU 38.
Metadata
Release files for django-fashion-size 0.10.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| django_fashion_size-0.10.0.tar.gz | 101.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_fashion_size-0.10.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 182.9 kB
Release files / django_fashion_size-0.10.0.tar.gz
| Download URL | django_fashion_size-0.10.0.tar.gz |
|---|---|
| Size | 101.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c70f8ae0907b0d4b666c7173e9f27907e90f5dee6b4c3c461159955a7d143121
|
|
BLAKE2b-256 checksum How to use checksums |
c67aac88d4d15a24f461de7511350f74c353c6828abcd7955d06ae19fab1e279
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logRelease files / django_fashion_size-0.10.0-py3-none-any.whl
| Download URL | django_fashion_size-0.10.0-py3-none-any.whl |
|---|---|
| Size | 81.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7fded4417d796995d493ce03e6e5853388a1dc1c656399856a47123b39c1c697
|
|
BLAKE2b-256 checksum How to use checksums |
66ec2c58b2638ca2e582d2e153b95d5006c937bb0718de8fc802743d2fddec48
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logSecurity for django-fashion-size 0.10.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for django_fashion_size-0.10.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.