4.6. Models Field Choices
models.TextChoices
- enum with strings as keys and strings as valuesmodels.IntegerChoices
- enum with integers as keys and strings as values
4.6.1. SetUp
>>> from django.db import models
>>> from django.utils.translation import gettext_lazy as _
4.6.2. TextChoices
Easier to read and understand
Easier to write raw SQL queries
Easier to debug
>>> class Language(models.TextChoices):
... EN = 'en', _('English')
... PL = 'pl', _('Polish')
... ES = 'es', _('Spanish')
... DE = 'de', _('German')
>>> language = models.CharField(
... verbose_name=_('Language'),
... max_length=2,
... null=True,
... blank=True,
... choices=Language,
... default=Language.EN,
... )
4.6.3. IntegerChoices
Easier to convert to ForeignKeyField or OneToOneField in the future
>>> class Language(models.IntegerChoices):
... EN = 1, _('English')
... PL = 2, _('Polish')
... ES = 3, _('Spanish')
... DE = 4, _('German')
>>> language = models.IntegerField(
... verbose_name=_('Language'),
... null=True,
... blank=True,
... choices=Language,
... default=Language.EN,
... )
4.6.4. Use Case - 1
>>>
... from django.db import models
... from django.utils.translation import gettext_lazy as _
...
...
... class Language(models.IntegerChoices):
... 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)
4.6.5. Use Case - 2
>>>
... 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}'
4.6.6. Use Case - 3
>>>
... 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)
4.6.7. Use Case - 4
>>>
... 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')
4.6.8. Use Case - 5
>>>
... 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')
4.6.9. Use Case - 6
>>>
... 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')
4.6.10. Assignments
# TODO: Create Tests
# doctest: +SKIP_FILE
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Django Model Choices
# - Difficulty: easy
# - Lines: 4
# - Minutes: 5
# %% English
# 0. Use `myproject.demo`
# 1. Add class `Language` as `models.TextChoices`:
# - ENGLISH = 'en', _('English')
# - POLISH = 'pl', _('Polish')
# 2. Alter model `Person`, add field `language` as `models.CharField`:
# - verbose_name=_('Language')
# - max_length=2
# - choices=Language
# - null=True
# - blank=True
# - default=Language.ENGLISH
# 3. Use `gettext_lazy`
# 4. Run `makemigrations`
# 5. Run `migrate`
# %% Polish
# 0. Użyj `myproject.demo`
# 1. Dodaj klasę `Language` jako `models.TextChoices`:
# - ENGLISH = 'en', _('English')
# - POLISH = 'pl', _('Polish')
# 2. Zmień model `Person`, dodaj pole `language` jako `models.CharField`:
# - verbose_name=_('Language')
# - max_length=2
# - choices=Language
# - null=True
# - blank=True
# - default=Language.ENGLISH
# 3. Użyj `gettext_lazy`
# 4. Uruchom `makemigrations`
# 5. Uruchom `migrate`
# %% Output
# - `Add field language to person`
# - `Applying demo.0007_person_language... OK`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 10), \
'Python 3.10+ required'
"""
from django.db import models
from django.utils.translation import gettext_lazy as _
class Person(models.Model):
language = ...
# TODO: Create Tests
# doctest: +SKIP_FILE
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Django Model Choices
# - Difficulty: easy
# - Lines: 4
# - Minutes: 5
# %% English
# 0. Use `myproject.demo`
# 1. Add class `Currency` as `models.IntegerChoices`:
# - USD = 1, _('US Dollar')
# - PLN = 2, _('Polish Zloty')
# 2. Alter model `Person`, add field `currency` as `models.IntegerField`:
# - verbose_name=_('Currency')
# - choices=Currency
# - null=True
# - blank=True
# - default=Currency.USD
# 3. Use `gettext_lazy`
# 4. Run `makemigrations`
# 5. Run `migrate`
# %% Polish
# 0. Użyj `myproject.demo`
# 1. Dodaj klasę `Currency` jako `models.IntegerChoices`:
# - USD = 1, _('US Dollar')
# - PLN = 2, _('Polish Zloty')
# 2. Zmień model `Person`, dodaj pole `currency` jako `models.IntegerField`:
# - verbose_name=_('Currency')
# - choices=Currency
# - null=True
# - blank=True
# - default=Currency.USD
# 3. Użyj `gettext_lazy`
# 4. Uruchom `makemigrations`
# 5. Uruchom `migrate`
# %% Output
# - `Add field currency to person`
# - `Applying demo.0007_person_currency... OK`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 10), \
'Python 3.10+ required'
"""
from django.db import models
from django.utils.translation import gettext_lazy as _
class Person(models.Model):
language = ...