5.5. Models Field Choices

  • models.TextChoices - enum with strings as keys and strings as values

  • models.IntegerChoices - enum with integers as keys and strings as values

>>> 
... from django.db import models
... from django.utils.translation import gettext_lazy as _
...
...
... class Language(models.TextChoices):
...     EN = 1, _('English')
...     PL = 2, _('Polish')
...     ES = 3, _('Spanish')
...     DE = 4, _('German')
...
... class Currency(models.TextChoices):
...     EUR = 'EUR', _('Euro')
...     PLN = 'PLN', _('Polish Zloty')
...     USD = 'USD', _('United States Dollar')
...
... class Customer(models.Model):
...     firstname = models.CharField(verbose_name=_('First Name'), max_length=50)
...     lastname = models.CharField(verbose_name=_('Last Name'), max_length=50, db_index=True)
...     language = models.IntegerField(verbose_name=_('Language'), null=True, default=Language.EN, choices=Language)
...     currency = models.CharField(verbose_name=_('Currency'), max_length=3, null=True, default=Language.EUR, choices=Language)

5.5.1. TextChoices

  • Easier to read and understand

  • Easier to write raw SQL queries

  • Easier to debug

>>> 
... class Language(models.TextChoices):
...     UNKNOWN = None, _('Unknown')
...     EN = 'en', _('English')
...     PL = 'pl', _('Polish')
...     ES = 'es', _('Spanish')
...     DE = 'de', _('German')
...
...
... class Customer(models.Model):
...     firstname = models.CharField(verbose_name=_('First Name'), max_length=50)
...     lastname = models.CharField(verbose_name=_('Last Name'), max_length=50, db_index=True)
...     language = models.CharField(verbose_name=_('Language'), max_length=2, null=True, default=Language.UNKNOWN, choices=Language)

5.5.2. IntegerChoices

  • Easier to convert to ForeignKeyField or OneToOneField in the future

>>> 
... class Language(models.TextChoices):
...     UNKNOWN = None, _('Unknown')
...     EN = 1, _('English')
...     PL = 2, _('Polish')
...     ES = 3, _('Spanish')
...     DE = 4, _('German')
...
...
... class Customer(models.Model):
...     firstname = models.CharField(verbose_name=_('First Name'), max_length=50)
...     lastname = models.CharField(verbose_name=_('Last Name'), max_length=50, db_index=True)
...     language = models.IntegerField(verbose_name=_('Language'), null=True, default=Language.UNKNOWN, choices=Language)

5.5.3. Use Case - 0x01

>>> 
... from django.db import models
... from django.utils.translation import gettext_lazy as _
...
...
... class AddressType(models.TextChoices):
...     HOME = 'home', _('Home')
...     WORK = 'work', _('Work')
...     BILLING = 'billing', _('Billing')
...     SHIPPING = 'shipping', _('Shipping')
...
...
... class Address(models.Model):
...     customer = models.ForeignKey(verbose_name=_('Customer'), to='shop.Customer', on_delete=models.CASCADE, related_name='address')
...     type = models.CharField(verbose_name=_('Type'), choices=AddressType, max_length=20, null=False, blank=False)
...     street = models.CharField(verbose_name=_('Street'), max_length=100, null=False, blank=False)
...     house = models.CharField(verbose_name=_('House Number'), max_length=20, null=False, blank=False)
...     apartment = models.CharField(verbose_name=_('Apartment Number'), max_length=20, null=True, blank=True, default=None)
...     postcode = models.CharField(verbose_name=_('Post Code'), max_length=20, null=False, blank=False)
...     city = models.CharField(verbose_name=_('City'), max_length=100, null=False, blank=False)
...     region = models.CharField(verbose_name=_('Region'), max_length=100, null=True, blank=True, default=None)
...     country = models.CharField(verbose_name=_('Country'), max_length=100, null=False, blank=False)
...
...     class Meta:
...         app_label = 'shop'
...         verbose_name = _('Address')
...         verbose_name_plural = _('Addresses')
...
...     def __str__(self):
...         return f'{self.street} {self.house}, {self.city}'

5.5.4. Use Case - 0x02

>>> # docstring: +SKIP
... from django.core.validators import MaxValueValidator, MinValueValidator
... from django.db import models
... from django.utils.translation import gettext_lazy as _
... from django.conf import settings
...
... class Language(models.TextChoices):
...     UNKNOWN = None, _('Unknown')
...     POLISH = 'polish', _('Polish')
...     ENGLISH = 'english', _('English')
...     HINDI = 'hindi', _('Hindi')
...     TAMIL = 'tamil', _('Tamil')
...
...
... class PhoneTypes(models.TextChoices):
...     WORK = 'work', _('Work')
...     HOME = 'home', _('Home')
...
...
... class PhoneCountryCodes(models.TextChoices):
...     USA = '+1', _('(+1) USA')
...     POLAND = '+48', _('(+48) Poland')
...     GERMANY = '+49', _('(+49) Germany')
...     INDIA = '+91', _('(+91) India')
...
...
... class Alive(models.IntegerChoices):
...     YES = True, _('Alive')
...     NO = False, _('Deceased')
...
...
... class Customer(models.Model):
...     # Personal Fields
...     firstname = models.CharField(verbose_name=_('First Name'), max_length=50)
...     lastname = models.CharField(verbose_name=_('Last Name'), max_length=50, db_index=True)
...     language = models.CharField(verbose_name=_('Language'), max_length=20, null=True, default=Language.UNKNOWN, choices=Language)
...     personal_identification_number = models.CharField(verbose_name=_('Personal Identification Number'), max_length=30, null=True, blank=True, default=None, help_text=_('This is country specific number such as SSN, PESEL'))
...
...     # Relations
...     groups = models.ManyToManyField(verbose_name=_('Group'), to='contact.Group', blank=True, limit_choices_to={'group__name__startswith': 'customer_'})
...     friends = models.ManyToManyField(verbose_name=_('Friends'), to='contact.Customer', blank=True)
...
...     # Biometric
...     is_alive = models.BooleanField(verbose_name=_('Is Alive?'), null=True, blank=True, default=None, choices=Alive.choices)
...     birthdate = models.DateField(verbose_name=_('Birthdate'), null=True, blank=True, default=None)
...     height = models.FloatField(verbose_name=_('Height'), null=True, blank=True, default=None, validators=[MinValueValidator(0), MaxValueValidator(250)], help_text=_('cm'))
...     weight = models.FloatField(verbose_name=_('Weight'), null=True, blank=True, default=None, validators=[MinValueValidator(0), MaxValueValidator(250)], help_text=_('kg'))
...     salary = models.DecimalField(verbose_name=_('Salary'), null=True, blank=True, default=None, max_digits=8, decimal_places=2, validators=[MinValueValidator(0), MaxValueValidator(300_000)], help_text=_('USD per year'))
...     image = models.ImageField(verbose_name=_('Image'), upload_to=upload_path, null=True, blank=True, default=None)
...
...     # Contact
...     current_company = models.CharField(verbose_name=_('Current Company'), max_length=50, null=True, blank=True, default=None)
...     current_position = models.CharField(verbose_name=_('Current Position'), max_length=50, null=True, blank=True, default=None)
...     email = models.EmailField(verbose_name=_('Email'), max_length=100, unique=True, null=True, blank=True, default=None)
...     phone_type = models.CharField(verbose_name=_('Phone Type'), max_length=15, null=True, blank=True, default=None, choices=PhoneTypes.choices)
...     phone_countrycode = models.CharField(verbose_name=_('Phone Country Code'), max_length=4, null=True, blank=True, default=None, choices=PhoneCountryCodes.choices)
...     phone_number = models.CharField(verbose_name=_('Phone Number'), max_length=10, null=True, blank=True, default=None)
...     homepage = models.URLField(verbose_name=_('Homepage'), null=True, blank=True, default=None)
...     notes = models.TextField(verbose_name=_('Notes'), null=True, blank=True, default=None)

5.5.5. Use Case - 0x03

>>> 
... from django.db import models
... from django.utils.translation import gettext_lazy as _
...
...
... class Species(models.TextChoices):
...     SETOSA = 'setosa', _('Setosa')
...     VIRGINICA = 'virginica', _('Virginica')
...     VERSICOLOR = 'versicolor', _('Versicolor')
...
...
... class Iris(models.Model):
...     sepal_length = models.FloatField(verbose_name=_('sepal_length'), null=True, blank=True, default=None)
...     sepal_width = models.FloatField(verbose_name=_('sepal_width'), null=True, blank=True, default=None)
...     petal_length = models.FloatField(verbose_name=_('petal_length'), null=True, blank=True, default=None)
...     petal_width = models.FloatField(verbose_name=_('petal_width'), null=True, blank=True, default=None)
...     species = models.CharField(verbose_name=_('species'), max_length=20, choices=Species, null=True, blank=True, default=None, db_index=True)
...
...     def __str__(self) -> str:
...         return f'{self.species}'
...
...     class Meta:
...         verbose_name = _('Iris')
...         verbose_name_plural = _('Irises')

5.5.6. Use Case - 0x04

>>> 
... class Language(models.TextChoices):
...     AA = 'AA', _('Afar')
...     AB = 'AB', _('Abkhaz')
...     AE = 'AE', _('Avestan')
...     AF = 'AF', _('Afrikaans')
...     AK = 'AK', _('Akan')
...     AM = 'AM', _('Amharic')
...     AN = 'AN', _('Aragonese')
...     AR = 'AR', _('Arabic')
...     AS = 'AS', _('Assamese')
...     AV = 'AV', _('Avaric')
...     AY = 'AY', _('Aymara')
...     AZ = 'AZ', _('Azerbaijani')
...     BA = 'BA', _('Bashkir')
...     BE = 'BE', _('Belarusian')
...     BG = 'BG', _('Bulgarian')
...     BH = 'BH', _('Bihari')
...     BI = 'BI', _('Bislama')
...     BM = 'BM', _('Bambara')
...     BN = 'BN', _('Bengali')
...     BO = 'BO', _('Tibetan')
...     BR = 'BR', _('Breton')
...     BS = 'BS', _('Bosnian')
...     CA = 'CA', _('Catalan')
...     CE = 'CE', _('Chechen')
...     CH = 'CH', _('Chamorro')
...     CO = 'CO', _('Corsican')
...     CR = 'CR', _('Cree')
...     CS = 'CS', _('Czech')
...     CU = 'CU', _('Church Slavic')
...     CV = 'CV', _('Chuvash')
...     CY = 'CY', _('Welsh')
...     DA = 'DA', _('Danish')
...     DE = 'DE', _('German')
...     DV = 'DV', _('Divehi')
...     EE = 'EE', _('Ewe')
...     EL = 'EL', _('Greek')
...     EN = 'EN', _('English')
...     EO = 'EO', _('Esperanto')
...     ES = 'ES', _('Spanish')
...     ET = 'ET', _('Estonian')
...     EU = 'EU', _('Basque')
...     FA = 'FA', _('Persian')
...     FF = 'FF', _('Fula')
...     FI = 'FI', _('Finnish')
...     FJ = 'FJ', _('Fijian')
...     FO = 'FO', _('Faroese')
...     FR = 'FR', _('French')
...     FY = 'FY', _('Frisian')
...     GA = 'GA', _('Irish')
...     GD = 'GD', _('Gaelic')
...     GL = 'GL', _('Galician')
...     GN = 'GN', _('Guaraní')
...     GU = 'GU', _('Gujarati')
...     GV = 'GV', _('Manx')
...     HA = 'HA', _('Hausa')
...     HE = 'HE', _('Hebrew')
...     HI = 'HI', _('Hindi')
...     HO = 'HO', _('Hiri Motu')
...     HR = 'HR', _('Croatian')
...     HT = 'HT', _('Haitian')
...     HU = 'HU', _('Hungarian')
...     HY = 'HY', _('Armenian')
...     HZ = 'HZ', _('Herero')
...     IA = 'IA', _('Interlingua')
...     ID = 'ID', _('Indonesian')
...     IE = 'IE', _('Interlingue')
...     IG = 'IG', _('Igbo')
...     II = 'II', _('Nuosu')
...     IK = 'IK', _('Inupiaq')
...     IO = 'IO', _('Ido')
...     IS = 'IS', _('Icelandic')
...     IT = 'IT', _('Italian')
...     IU = 'IU', _('Inuktitut')
...     JA = 'JA', _('Japanese')
...     JV = 'JV', _('Javanese')
...     KA = 'KA', _('Georgian')
...     KG = 'KG', _('Kongo')
...     KI = 'KI', _('Kikuyu')
...     KJ = 'KJ', _('Kwanyama')
...     KK = 'KK', _('Kazakh')
...     KL = 'KL', _('Kalaallisut')
...     KM = 'KM', _('Khmer')
...     KN = 'KN', _('Kannada')
...     KO = 'KO', _('Korean')
...     KR = 'KR', _('Kanuri')
...     KS = 'KS', _('Kashmiri')
...     KU = 'KU', _('Kurdish')
...     KV = 'KV', _('Komi')
...     KW = 'KW', _('Cornish')
...     KY = 'KY', _('Kirghiz')
...     LA = 'LA', _('Latin')
...     LB = 'LB', _('Luxembourgish')
...     LG = 'LG', _('Luganda')
...     LI = 'LI', _('Limburgish')
...     LN = 'LN', _('Lingala')
...     LO = 'LO', _('Lao')
...     LT = 'LT', _('Lithuanian')
...     LU = 'LU', _('Luba-Katanga')
...     LV = 'LV', _('Latvian')
...     MG = 'MG', _('Malagasy')
...     MH = 'MH', _('Marshallese')
...     MI = 'MI', _('Māori')
...     MK = 'MK', _('Macedonian')
...     ML = 'ML', _('Malayalam')
...     MN = 'MN', _('Mongolian')
...     MR = 'MR', _('Marathi')
...     MS = 'MS', _('Malay')
...     MT = 'MT', _('Maltese')
...     MY = 'MY', _('Burmese')
...     NA = 'NA', _('Nauru')
...     NB = 'NB', _('Bokmål')
...     ND = 'ND', _('Ndebele')
...     NE = 'NE', _('Nepali')
...     NG = 'NG', _('Ndonga')
...     NL = 'NL', _('Dutch')
...     NN = 'NN', _('Nynorsk')
...     NO = 'NO', _('Norwegian')
...     NR = 'NR', _('Ndebele')
...     NV = 'NV', _('Navajo')
...     NY = 'NY', _('Chichewa')
...     OC = 'OC', _('Occitan')
...     OJ = 'OJ', _('Ojibwe')
...     OM = 'OM', _('Oromo')
...     OR = 'OR', _('Oriya')
...     OS = 'OS', _('Ossetian')
...     PA = 'PA', _('Panjabi')
...     PI = 'PI', _('Pāli')
...     PL = 'PL', _('Polish')
...     PS = 'PS', _('Pashto')
...     PT = 'PT', _('Portuguese')
...     QU = 'QU', _('Quechua')
...     RM = 'RM', _('Romansh')
...     RN = 'RN', _('Kirundi')
...     RO = 'RO', _('Romanian')
...     RU = 'RU', _('Russian')
...     RW = 'RW', _('Kinyarwanda')
...     SA = 'SA', _('Sanskrit')
...     SC = 'SC', _('Sardinian')
...     SD = 'SD', _('Sindhi')
...     SE = 'SE', _('Sami')
...     SG = 'SG', _('Sango')
...     SI = 'SI', _('Sinhala')
...     SK = 'SK', _('Slovak')
...     SL = 'SL', _('Slovene')
...     SM = 'SM', _('Samoan')
...     SN = 'SN', _('Shona')
...     SO = 'SO', _('Somali')
...     SQ = 'SQ', _('Albanian')
...     SR = 'SR', _('Serbian')
...     SS = 'SS', _('Swati')
...     ST = 'ST', _('Sotho')
...     SU = 'SU', _('Sundanese')
...     SV = 'SV', _('Swedish')
...     SW = 'SW', _('Swahili')
...     TA = 'TA', _('Tamil')
...     TE = 'TE', _('Telugu')
...     TG = 'TG', _('Tajik')
...     TH = 'TH', _('Thai')
...     TI = 'TI', _('Tigrinya')
...     TK = 'TK', _('Turkmen')
...     TL = 'TL', _('Tagalog')
...     TN = 'TN', _('Tswana')
...     TO = 'TO', _('Tonga')
...     TR = 'TR', _('Turkish')
...     TS = 'TS', _('Tsonga')
...     TT = 'TT', _('Tatar')
...     TW = 'TW', _('Twi')
...     TY = 'TY', _('Tahitian')
...     UG = 'UG', _('Uighur')
...     UK = 'UK', _('Ukrainian')
...     UR = 'UR', _('Urdu')
...     UZ = 'UZ', _('Uzbek')
...     VE = 'VE', _('Venda')
...     VI = 'VI', _('Vietnamese')
...     VO = 'VO', _('Volapük')
...     WA = 'WA', _('Walloon')
...     WO = 'WO', _('Wolof')
...     XH = 'XH', _('Xhosa')
...     YI = 'YI', _('Yiddish')
...     YO = 'YO', _('Yoruba')
...     ZA = 'ZA', _('Zhuang')
...     ZH = 'ZH', _('Chinese')

5.5.7. Use Case - 0x05

>>> 
... class Currency(models.TextChoices):
...     AED = 'AED', _('United Arab Emirates Dirham')
...     AFN = 'AFN', _('Afghan Afghani')
...     ALL = 'ALL', _('Albanian Lek')
...     AMD = 'AMD', _('Armenian Dram')
...     ANG = 'ANG', _('Netherlands Antillean Guilder')
...     AOA = 'AOA', _('Angolan Kwanza')
...     ARS = 'ARS', _('Argentine Peso')
...     AUD = 'AUD', _('Australian Dollar')
...     AWG = 'AWG', _('Aruban Florin')
...     AZN = 'AZN', _('Azerbaijani Manat')
...     BAM = 'BAM', _('Bosnia-Herzegovina Convertible Mark')
...     BBD = 'BBD', _('Barbadian Dollar')
...     BDT = 'BDT', _('Bangladeshi Taka')
...     BGN = 'BGN', _('Bulgarian Lev')
...     BHD = 'BHD', _('Bahraini Dinar')
...     BIF = 'BIF', _('Burundian Franc')
...     BMD = 'BMD', _('Bermudan Dollar')
...     BND = 'BND', _('Brunei Dollar')
...     BOB = 'BOB', _('Bolivian Boliviano')
...     BRL = 'BRL', _('Brazilian Real')
...     BSD = 'BSD', _('Bahamian Dollar')
...     BTC = 'BTC', _('Bitcoin')
...     BTN = 'BTN', _('Bhutanese Ngultrum')
...     BWP = 'BWP', _('Botswanan Pula')
...     BYN = 'BYN', _('Belarusian Ruble')
...     BZD = 'BZD', _('Belize Dollar')
...     CAD = 'CAD', _('Canadian Dollar')
...     CDF = 'CDF', _('Congolese Franc')
...     CHF = 'CHF', _('Swiss Franc')
...     CLF = 'CLF', _('Chilean Unit of Account (UF)')
...     CLP = 'CLP', _('Chilean Peso')
...     CNH = 'CNH', _('Chinese Yuan (Offshore)')
...     CNY = 'CNY', _('Chinese Yuan')
...     COP = 'COP', _('Colombian Peso')
...     CRC = 'CRC', _('Costa Rican Colón')
...     CUC = 'CUC', _('Cuban Convertible Peso')
...     CUP = 'CUP', _('Cuban Peso')
...     CVE = 'CVE', _('Cape Verdean Escudo')
...     CZK = 'CZK', _('Czech Republic Koruna')
...     DJF = 'DJF', _('Djiboutian Franc')
...     DKK = 'DKK', _('Danish Krone')
...     DOP = 'DOP', _('Dominican Peso')
...     DZD = 'DZD', _('Algerian Dinar')
...     EGP = 'EGP', _('Egyptian Pound')
...     ERN = 'ERN', _('Eritrean Nakfa')
...     ETB = 'ETB', _('Ethiopian Birr')
...     EUR = 'EUR', _('Euro')
...     FJD = 'FJD', _('Fijian Dollar')
...     FKP = 'FKP', _('Falkland Islands Pound')
...     GBP = 'GBP', _('British Pound Sterling')
...     GEL = 'GEL', _('Georgian Lari')
...     GGP = 'GGP', _('Guernsey Pound')
...     GHS = 'GHS', _('Ghanaian Cedi')
...     GIP = 'GIP', _('Gibraltar Pound')
...     GMD = 'GMD', _('Gambian Dalasi')
...     GNF = 'GNF', _('Guinean Franc')
...     GTQ = 'GTQ', _('Guatemalan Quetzal')
...     GYD = 'GYD', _('Guyanaese Dollar')
...     HKD = 'HKD', _('Hong Kong Dollar')
...     HNL = 'HNL', _('Honduran Lempira')
...     HRK = 'HRK', _('Croatian Kuna')
...     HTG = 'HTG', _('Haitian Gourde')
...     HUF = 'HUF', _('Hungarian Forint')
...     IDR = 'IDR', _('Indonesian Rupiah')
...     ILS = 'ILS', _('Israeli New Sheqel')
...     IMP = 'IMP', _('Manx pound')
...     INR = 'INR', _('Indian Rupee')
...     IQD = 'IQD', _('Iraqi Dinar')
...     IRR = 'IRR', _('Iranian Rial')
...     ISK = 'ISK', _('Icelandic Króna')
...     JEP = 'JEP', _('Jersey Pound')
...     JMD = 'JMD', _('Jamaican Dollar')
...     JOD = 'JOD', _('Jordanian Dinar')
...     JPY = 'JPY', _('Japanese Yen')
...     KES = 'KES', _('Kenyan Shilling')
...     KGS = 'KGS', _('Kyrgystani Som')
...     KHR = 'KHR', _('Cambodian Riel')
...     KMF = 'KMF', _('Comorian Franc')
...     KPW = 'KPW', _('North Korean Won')
...     KRW = 'KRW', _('South Korean Won')
...     KWD = 'KWD', _('Kuwaiti Dinar')
...     KYD = 'KYD', _('Cayman Islands Dollar')
...     KZT = 'KZT', _('Kazakhstani Tenge')
...     LAK = 'LAK', _('Laotian Kip')
...     LBP = 'LBP', _('Lebanese Pound')
...     LKR = 'LKR', _('Sri Lankan Rupee')
...     LRD = 'LRD', _('Liberian Dollar')
...     LSL = 'LSL', _('Lesotho Loti')
...     LYD = 'LYD', _('Libyan Dinar')
...     MAD = 'MAD', _('Moroccan Dirham')
...     MDL = 'MDL', _('Moldovan Leu')
...     MGA = 'MGA', _('Malagasy Ariary')
...     MKD = 'MKD', _('Macedonian Denar')
...     MMK = 'MMK', _('Myanma Kyat')
...     MNT = 'MNT', _('Mongolian Tugrik')
...     MOP = 'MOP', _('Macanese Pataca')
...     MRU = 'MRU', _('Mauritanian Ouguiya')
...     MUR = 'MUR', _('Mauritian Rupee')
...     MVR = 'MVR', _('Maldivian Rufiyaa')
...     MWK = 'MWK', _('Malawian Kwacha')
...     MXN = 'MXN', _('Mexican Peso')
...     MYR = 'MYR', _('Malaysian Ringgit')
...     MZN = 'MZN', _('Mozambican Metical')
...     NAD = 'NAD', _('Namibian Dollar')
...     NGN = 'NGN', _('Nigerian Naira')
...     NIO = 'NIO', _('Nicaraguan Córdoba')
...     NOK = 'NOK', _('Norwegian Krone')
...     NPR = 'NPR', _('Nepalese Rupee')
...     NZD = 'NZD', _('New Zealand Dollar')
...     OMR = 'OMR', _('Omani Rial')
...     PAB = 'PAB', _('Panamanian Balboa')
...     PEN = 'PEN', _('Peruvian Nuevo Sol')
...     PGK = 'PGK', _('Papua New Guinean Kina')
...     PHP = 'PHP', _('Philippine Peso')
...     PKR = 'PKR', _('Pakistani Rupee')
...     PLN = 'PLN', _('Polish Zloty')
...     PYG = 'PYG', _('Paraguayan Guarani')
...     QAR = 'QAR', _('Qatari Rial')
...     RON = 'RON', _('Romanian Leu')
...     RSD = 'RSD', _('Serbian Dinar')
...     RUB = 'RUB', _('Russian Ruble')
...     RWF = 'RWF', _('Rwandan Franc')
...     SAR = 'SAR', _('Saudi Riyal')
...     SBD = 'SBD', _('Solomon Islands Dollar')
...     SCR = 'SCR', _('Seychellois Rupee')
...     SDG = 'SDG', _('Sudanese Pound')
...     SEK = 'SEK', _('Swedish Krona')
...     SGD = 'SGD', _('Singapore Dollar')
...     SHP = 'SHP', _('Saint Helena Pound')
...     SLL = 'SLL', _('Sierra Leonean Leone')
...     SOS = 'SOS', _('Somali Shilling')
...     SRD = 'SRD', _('Surinamese Dollar')
...     SSP = 'SSP', _('South Sudanese Pound')
...     STD = 'STD', _('São Tomé and Príncipe Dobra (pre-2018)')
...     STN = 'STN', _('São Tomé and Príncipe Dobra')
...     SVC = 'SVC', _('Salvadoran Colón')
...     SYP = 'SYP', _('Syrian Pound')
...     SZL = 'SZL', _('Swazi Lilangeni')
...     THB = 'THB', _('Thai Baht')
...     TJS = 'TJS', _('Tajikistani Somoni')
...     TMT = 'TMT', _('Turkmenistani Manat')
...     TND = 'TND', _('Tunisian Dinar')
...     TOP = 'TOP', _("Tongan Pa'anga")
...     TRY = 'TRY', _('Turkish Lira')
...     TTD = 'TTD', _('Trinidad and Tobago Dollar')
...     TWD = 'TWD', _('New Taiwan Dollar')
...     TZS = 'TZS', _('Tanzanian Shilling')
...     UAH = 'UAH', _('Ukrainian Hryvnia')
...     UGX = 'UGX', _('Ugandan Shilling')
...     USD = 'USD', _('United States Dollar')
...     UYU = 'UYU', _('Uruguayan Peso')
...     UZS = 'UZS', _('Uzbekistan Som')
...     VEF = 'VEF', _('Venezuelan Bolívar Fuerte (Old)')
...     VES = 'VES', _('Venezuelan Bolívar Soberano')
...     VND = 'VND', _('Vietnamese Dong')
...     VUV = 'VUV', _('Vanuatu Vatu')
...     WST = 'WST', _('Samoan Tala')
...     XAF = 'XAF', _('CFA Franc BEAC')
...     XAG = 'XAG', _('Silver Ounce')
...     XAU = 'XAU', _('Gold Ounce')
...     XCD = 'XCD', _('East Caribbean Dollar')
...     XDR = 'XDR', _('Special Drawing Rights')
...     XOF = 'XOF', _('CFA Franc BCEAO')
...     XPD = 'XPD', _('Palladium Ounce')
...     XPF = 'XPF', _('CFP Franc')
...     XPT = 'XPT', _('Platinum Ounce')
...     YER = 'YER', _('Yemeni Rial')
...     ZAR = 'ZAR', _('South African Rand')
...     ZMW = 'ZMW', _('Zambian Kwacha')
...     ZWL = 'ZWL', _('Zimbabwean Dolla')