Creating Select form fields with currencies and countries using Babel and WTForms
A quick tutorial on how to create some nifty currency and country select fields using WTForms. This was sort of a headache to figure out, which is why I’m sharing it. If you have a cleaner way to do this (particularly the country list), please comment, because I’m highly dissatisfied with hardcoding the countries and would love to pull them out of Babel but couldn’t find a way to do it.
Let’s assume that you’ve already created your Form object in WTForms and that you have some kind of country and currency fields in the form. The fields should be SelectField objects, as in the sample form below:
1 2 3 4 5 | from utils import get_countries, get_currencies class CountryInfo(Form): name = SelectField('Name', choices=get_countries()) currency = SelectField('Currency', choices=get_currencies()) |
So here we’ve defined two Select Fields with labels ‘Name’ and ‘Currency’, and we’re generating the choices in our utility methods. SelectField objects automatically use HTML Select boxes (go figure, right?), and so all we need to do now is create the methods that generate the list of tuples to populate those boxes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | from babel.core import Locale def get_currencies(): """ Returns a list of tuples with a value (USD) and the key-value pair as the label. Taken from Babel's Locale.parse('en_US').currencies dictionary. """ return [(k, '%s (%s)' % (v, k)) for k,v in Locale.parse('en_US').currencies.items()] def get_countries(): """ Returns a a list of tuples with identical country string values to be used in option select boxes. """ return [("Afganistan","Afganistan"), ("Albania","Albania"), ("Algeria","Algeria"), ("American Samoa","American Samoa"), ("Andorra","Andorra"), ("Angola","Angola"), ("Anguilla","Anguilla"), ("Antigua & Barbuda","Antigua & Barbuda"), ("Argentina","Argentina"), ("Armenia","Armenia"), ("Aruba","Aruba"), ("Australia","Australia"), ("Austria","Austria"), ("Azerbaijan","Azerbaijan"), ("Bahamas","Bahamas"), ("Bahrain","Bahrain"), ("Bangladesh","Bangladesh"), ("Barbados","Barbados"), ("Belarus","Belarus"), ("Belgium","Belgium"), ("Belize","Belize"), ("Benin","Benin"), ("Bermuda","Bermuda"), ("Bhutan","Bhutan"), ("Bolivia","Bolivia"), ("Bonaire","Bonaire"), ("Bosnia & Herzegovina","Bosnia & Herzegovina"), ("Botswana","Botswana"), ("Brazil","Brazil"), ("British Indian Ocean Ter","British Indian Ocean Ter"), ("Brunei","Brunei"), ("Bulgaria","Bulgaria"), ("Burkina Faso","Burkina Faso"), ("Burundi","Burundi"), ("Cambodia","Cambodia"), ("Cameroon","Cameroon"), ("Canada","Canada"), ("Canary Islands","Canary Islands"), ("Cape Verde","Cape Verde"), ("Cayman Islands","Cayman Islands"), ("Central African Republic","Central African Republic"), ("Chad","Chad"), ("Channel Islands","Channel Islands"), ("Chile","Chile"), ("China","China"), ("Christmas Island","Christmas Island"), ("Cocos Island","Cocos Island"), ("Colombia","Colombia"), ("Comoros","Comoros"), ("Congo","Congo"), ("Cook Islands","Cook Islands"), ("Costa Rica","Costa Rica"), ("Cote DIvoire","Cote DIvoire"), ("Croatia","Croatia"), ("Cuba","Cuba"), ("Curaco","Curaco"), ("Cyprus","Cyprus"), ("Czech Republic","Czech Republic"), ("Denmark","Denmark"), ("Djibouti","Djibouti"), ("Dominica","Dominica"), ("Dominican Republic","Dominican Republic"), ("East Timor","East Timor"), ("Ecuador","Ecuador"), ("Egypt","Egypt"), ("El Salvador","El Salvador"), ("Equatorial Guinea","Equatorial Guinea"), ("Eritrea","Eritrea"), ("Estonia","Estonia"), ("Ethiopia","Ethiopia"), ("Falkland Islands","Falkland Islands"), ("Faroe Islands","Faroe Islands"), ("Fiji","Fiji"), ("Finland","Finland"), ("France","France"), ("French Guiana","French Guiana"), ("French Polynesia","French Polynesia"), ("French Southern Ter","French Southern Ter"), ("Gabon","Gabon"), ("Gambia","Gambia"), ("Georgia","Georgia"), ("Germany","Germany"), ("Ghana","Ghana"), ("Gibraltar","Gibraltar"), ("Great Britain","Great Britain"), ("Greece","Greece"), ("Greenland","Greenland"), ("Grenada","Grenada"), ("Guadeloupe","Guadeloupe"), ("Guam","Guam"), ("Guatemala","Guatemala"), ("Guinea","Guinea"), ("Guyana","Guyana"), ("Haiti","Haiti"), ("Hawaii","Hawaii"), ("Honduras","Honduras"), ("Hong Kong","Hong Kong"), ("Hungary","Hungary"), ("Iceland","Iceland"), ("India","India"), ("Indonesia","Indonesia"), ("Iran","Iran"), ("Iraq","Iraq"), ("Ireland","Ireland"), ("Isle of Man","Isle of Man"), ("Israel","Israel"), ("Italy","Italy"), ("Jamaica","Jamaica"), ("Japan","Japan"), ("Jordan","Jordan"), ("Kazakhstan","Kazakhstan"), ("Kenya","Kenya"), ("Kiribati","Kiribati"), ("Korea North","Korea North"), ("Korea Sout","Korea Sout"), ("Kuwait","Kuwait"), ("Kyrgyzstan","Kyrgyzstan"), ("Laos","Laos"), ("Latvia","Latvia"), ("Lebanon","Lebanon"), ("Lesotho","Lesotho"), ("Liberia","Liberia"), ("Libya","Libya"), ("Liechtenstein","Liechtenstein"), ("Lithuania","Lithuania"), ("Luxembourg","Luxembourg"), ("Macau","Macau"), ("Macedonia","Macedonia"), ("Madagascar","Madagascar"), ("Malaysia","Malaysia"), ("Malawi","Malawi"), ("Maldives","Maldives"), ("Mali","Mali"), ("Malta","Malta"), ("Marshall Islands","Marshall Islands"), ("Martinique","Martinique"), ("Mauritania","Mauritania"), ("Mauritius","Mauritius"), ("Mayotte","Mayotte"), ("Mexico","Mexico"), ("Midway Islands","Midway Islands"), ("Moldova","Moldova"), ("Monaco","Monaco"), ("Mongolia","Mongolia"), ("Montserrat","Montserrat"), ("Morocco","Morocco"), ("Mozambique","Mozambique"), ("Myanmar","Myanmar"), ("Nambia","Nambia"), ("Nauru","Nauru"), ("Nepal","Nepal"), ("Netherland Antilles","Netherland Antilles"), ("Netherlands","Netherlands"), ("Nevis","Nevis"), ("New Caledonia","New Caledonia"), ("New Zealand","New Zealand"), ("Nicaragua","Nicaragua"), ("Niger","Niger"), ("Nigeria","Nigeria"), ("Niue","Niue"), ("Norfolk Island","Norfolk Island"), ("Norway","Norway"), ("Oman","Oman"), ("Pakistan","Pakistan"), ("Palau Island","Palau Island"), ("Palestine","Palestine"), ("Panama","Panama"), ("Papua New Guinea","Papua New Guinea"), ("Paraguay","Paraguay"), ("Peru","Peru"), ("Phillipines","Phillipines"), ("Pitcairn Island","Pitcairn Island"), ("Poland","Poland"), ("Portugal","Portugal"), ("Puerto Rico","Puerto Rico"), ("Qatar","Qatar"), ("Republic of Montenegro","Republic of Montenegro"), ("Republic of Serbia","Republic of Serbia"), ("Reunion","Reunion"), ("Romania","Romania"), ("Russia","Russia"), ("Rwanda","Rwanda"), ("St Barthelemy","St Barthelemy"), ("St Eustatius","St Eustatius"), ("St Helena","St Helena"), ("St Kitts-Nevis","St Kitts-Nevis"), ("St Lucia","St Lucia"), ("St Maarten","St Maarten"), ("St Pierre & Miquelon","St Pierre & Miquelon"), ("St Vincent & Grenadines","St Vincent & Grenadines"), ("Saipan","Saipan"), ("Samoa","Samoa"), ("Samoa American","Samoa American"), ("San Marino","San Marino"), ("Sao Tome & Principe","Sao Tome & Principe"), ("Saudi Arabia","Saudi Arabia"), ("Senegal","Senegal"), ("Seychelles","Seychelles"), ("Sierra Leone","Sierra Leone"), ("Singapore","Singapore"), ("Slovakia","Slovakia"), ("Slovenia","Slovenia"), ("Solomon Islands","Solomon Islands"), ("Somalia","Somalia"), ("South Africa","South Africa"), ("Spain","Spain"), ("Sri Lanka","Sri Lanka"), ("Sudan","Sudan"), ("Suriname","Suriname"), ("Swaziland","Swaziland"), ("Sweden","Sweden"), ("Switzerland","Switzerland"), ("Syria","Syria"), ("Tahiti","Tahiti"), ("Taiwan","Taiwan"), ("Tajikistan","Tajikistan"), ("Tanzania","Tanzania"), ("Thailand","Thailand"), ("Togo","Togo"), ("Tokelau","Tokelau"), ("Tonga","Tonga"), ("Trinidad & Tobago","Trinidad & Tobago"), ("Tunisia","Tunisia"), ("Turkey","Turkey"), ("Turkmenistan","Turkmenistan"), ("Turks & Caicos Is","Turks & Caicos Is"), ("Tuvalu","Tuvalu"), ("Uganda","Uganda"), ("Ukraine","Ukraine"), ("United Arab Erimates","United Arab Erimates"), ("United Kingdom","United Kingdom"), ("United States of America","United States of America"), ("Uraguay","Uraguay"), ("Uzbekistan","Uzbekistan"), ("Vanuatu","Vanuatu"), ("Vatican City State","Vatican City State"), ("Venezuela","Venezuela"), ("Vietnam","Vietnam"), ("Virgin Islands (Brit)","Virgin Islands (Brit)"), ("Virgin Islands (USA)","Virgin Islands (USA)"), ("Wake Island","Wake Island"), ("Wallis & Futana Is","Wallis & Futana Is"), ("Yemen","Yemen"), ("Zaire","Zaire"), ("Zambia","Zambia"), ("Zimbabwe","Zimbabwe")] |
The first function makes use of Babel’s Locale object, which has a currencies dictionary from which we can pull the key-value pairs currency symbol and currency name, and put them into a list of tuples, which is the format our WTForms SelectField is expecting. The first string in each tuple is the option value, the second is the option label.
Our second function is very self-explanatory, returning a static list of identical country names tuples (you could obviously change this to make the values country codes instead, if that’s what your application requires). I scraped the list of countries from this site (can’t really remember, there are tons of country lists available), but I would have loved to pull it from Babel or an API call instead but couldn’t figure out how. Would welcome suggestions
One last thing: to assign a default value, simply use WTForms default named keyword, as in: default=”United States of America”. A caution, though: it seems to use the label, not the value. We skipped this entirely, though, because model object values override any default you may set, so we put our defaults in the model objects (we’re using SQLAlchemy, which has a default keyword for the column as well).
Hope this helped anyone confronting the same task!
-
Aguy