Source code for siruta.forms
import json
from django import forms
from django.core.exceptions import ValidationError
from django.forms import widgets
from django.utils.choices import normalize_choices
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _
from .data import COUNTIES_BY_ID
from .extras import LOCALITIES_BY_COUNTY_ID
from .extras import LOCALITIES_BY_ID
COUNTY_CHOICES = (("", ""), *COUNTIES_BY_ID.items())
LOCALITY_JSON = json.dumps(
{
county_id: [{"text": locality_name, "value": locality_id} for locality_id, locality_name in localities.items()]
for county_id, localities in LOCALITIES_BY_COUNTY_ID.items()
}
)
[docs]
class CountyField(forms.TypedChoiceField):
"""
An integer field with choices.
"""
[docs]
def __init__(self, **kwargs):
super().__init__(choices=COUNTY_CHOICES, coerce=int, **kwargs)
[docs]
class LocalityField(forms.Field):
"""
An integer field with choices.
The default widget dynamically changes choices depending on another form field named ``"county"``.
Override ``county_field`` to change this.
Values are ordered by type.
See ``siruta.cli.SIRUTA_TYPE_REORDER`` for exact precedence.
"""
[docs]
def __init__(self, *, county_field="county", **kwargs):
super().__init__(
widget=LocalityWidget(county_field=county_field),
**kwargs,
)
self.choices = normalize_choices(LOCALITIES_BY_ID)
[docs]
def to_python(self, value):
locality_id, county_id = value
if locality_id:
try:
locality_id = int(locality_id)
county_id = int(county_id)
except ValueError as exc:
raise ValidationError(_("Invalid value {value}.").format(value=repr(value))) from exc
county = COUNTIES_BY_ID.get(county_id)
if not county:
raise ValidationError(_("Invalid county ID '{id}'.").format(id=county_id))
locality = LOCALITIES_BY_ID.get(locality_id)
if not locality:
raise ValidationError(_("Invalid locality ID '{id}'.").format(id=locality_id))
county_localities = LOCALITIES_BY_COUNTY_ID[county_id]
if locality_id not in county_localities:
raise ValidationError(
_("Locality '{locality}' is not valid for county '{county}'.").format(
county=county,
locality=locality,
)
)
return locality_id
else:
return None