1 | # Based on http://code.djangoproject.com/ticket/5446
|
---|
2 | # Should be changed to use upstream code once it has been merged into it.
|
---|
3 |
|
---|
4 | from django.conf import settings
|
---|
5 | from django.contrib.gis import utils as gis_utils
|
---|
6 | from django.db.models import fields
|
---|
7 | from django.utils import encoding as utils_encoding
|
---|
8 | from django.utils import translation
|
---|
9 | from django.utils.translation import ugettext_lazy as _
|
---|
10 |
|
---|
11 | # Countries list - ISO 3166-1
|
---|
12 | # http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
|
---|
13 | # http://en.wikipedia.org/wiki/List_of_national_capitals
|
---|
14 |
|
---|
15 | COUNTRIES = (
|
---|
16 | ('AD', _('Andorra'), _('Andorra la Vella')),
|
---|
17 | ('AE', _('United Arab Emirates'), _('Abu Dhabi')),
|
---|
18 | ('AF', _('Afghanistan'), _('Kabul')),
|
---|
19 | ('AG', _('Antigua and Barbuda'), _("St. John's")),
|
---|
20 | ('AI', _('Anguilla'), _('The Valley')),
|
---|
21 | ('AL', _('Albania'), _('Tirana')),
|
---|
22 | ('AM', _('Armenia'), _('Yerevan')),
|
---|
23 | ('AN', _('Netherlands Antilles'), _('Willemstad')),
|
---|
24 | ('AO', _('Angola'), _('Luanda')),
|
---|
25 | ('AQ', _('Antarctica'), ''),
|
---|
26 | ('AR', _('Argentina'), _('Buenos Aires')),
|
---|
27 | ('AS', _('American Samoa'), _('Pago Pago')),
|
---|
28 | ('AT', _('Austria'), _('Vienna')),
|
---|
29 | ('AU', _('Australia'), _('Canberra')),
|
---|
30 | ('AW', _('Aruba'), _('Oranjestad')),
|
---|
31 | ('AX', _('Aland Islands'), _('Mariehamn')),
|
---|
32 | ('AZ', _('Azerbaijan'), _('Baku')),
|
---|
33 | ('BA', _('Bosnia and Herzegovina'), _('Sarajevo')),
|
---|
34 | ('BB', _('Barbados'), _('Bridgetown')),
|
---|
35 | ('BD', _('Bangladesh'), _('Dhaka')),
|
---|
36 | ('BE', _('Belgium'), _('Brussels')),
|
---|
37 | ('BF', _('Burkina Faso'), _('Ouagadougou')),
|
---|
38 | ('BG', _('Bulgaria'), _('Sofia')),
|
---|
39 | ('BH', _('Bahrain'), _('Manama')),
|
---|
40 | ('BI', _('Burundi'), _('Bujumbura')),
|
---|
41 | ('BJ', _('Benin'), _('Porto-Novo')),
|
---|
42 | ('BL', _('Saint Barthelemy'), _('Gustavia')),
|
---|
43 | ('BM', _('Bermuda'), _('Hamilton')),
|
---|
44 | ('BN', _('Brunei'), _('Bandar Seri Begawan')),
|
---|
45 | ('BO', _('Bolivia'), _('Sucre')),
|
---|
46 | ('BR', _('Brazil'), _('Brasilia')),
|
---|
47 | ('BS', _('Bahamas'), _('Nassau')),
|
---|
48 | ('BT', _('Bhutan'), _('Thimphu')),
|
---|
49 | ('BV', _('Bouvet Island'), ''),
|
---|
50 | ('BW', _('Botswana'), _('Gaborone')),
|
---|
51 | ('BY', _('Belarus'), _('Minsk')),
|
---|
52 | ('BZ', _('Belize'), _('Belmopan')),
|
---|
53 | ('CA', _('Canada'), _('Ottawa')),
|
---|
54 | ('CC', _('Cocos (Keeling) Islands'), _('West Island')),
|
---|
55 | ('CD', _('Congo, the Democratic Republic of the'), _('Kinshasa')),
|
---|
56 | ('CF', _('Central African Republic'), _('Bangui')),
|
---|
57 | ('CG', _('Congo, the Republic of the'), _('Brazzaville')),
|
---|
58 | ('CH', _('Switzerland'), _('Bern')),
|
---|
59 | ('CI', _('Ivory Coast'), _('Yamoussoukro')),
|
---|
60 | ('CK', _('Cook Islands'), _('Avarua')),
|
---|
61 | ('CL', _('Chile'), _('Santiago')),
|
---|
62 | ('CM', _('Cameroon'), _('Yaounde')),
|
---|
63 | ('CN', _('China'), _('Beijing')),
|
---|
64 | ('CO', _('Colombia'), _('Bogota')),
|
---|
65 | ('CR', _('Costa Rica'), _('San Jose')),
|
---|
66 | ('CU', _('Cuba'), _('Havana')),
|
---|
67 | ('CV', _('Cape Verde'), _('Praia')),
|
---|
68 | ('CX', _('Christmas Island'), _('Flying Fish Cove')),
|
---|
69 | ('CY', _('Cyprus'), _('Nicosia')),
|
---|
70 | ('CZ', _('Czech Republic'), _('Prague')),
|
---|
71 | ('DE', _('Germany'), _('Berlin')),
|
---|
72 | ('DJ', _('Djibouti'), _('Djibouti')),
|
---|
73 | ('DK', _('Denmark'), _('Copenhagen')),
|
---|
74 | ('DM', _('Dominica'), _('Roseau')),
|
---|
75 | ('DO', _('Dominican Republic'), _('Santo Domingo')),
|
---|
76 | ('DZ', _('Algeria'), _('Algiers')),
|
---|
77 | ('EC', _('Ecuador'), _('Quito')),
|
---|
78 | ('EE', _('Estonia'), _('Tallinn')),
|
---|
79 | ('EG', _('Egypt'), _('Cairo')),
|
---|
80 | ('EH', _('Western Sahara'), _('El Aaiun')),
|
---|
81 | ('ER', _('Eritrea'), _('Asmara')),
|
---|
82 | ('ES', _('Spain'), _('Madrid')),
|
---|
83 | ('ET', _('Ethiopia'), _('Addis Ababa')),
|
---|
84 | ('FI', _('Finland'), _('Helsinki')),
|
---|
85 | ('FJ', _('Fiji'), _('Suva')),
|
---|
86 | ('FK', _('Falkland Islands'), _('Stanley')),
|
---|
87 | ('FM', _('Micronesia'), _('Palikir')),
|
---|
88 | ('FO', _('Faroe Islands'), _('Torshavn')),
|
---|
89 | ('FR', _('France'), _('Paris')),
|
---|
90 | ('GA', _('Gabon'), _('Libreville')),
|
---|
91 | ('GB', _('United Kingdom'), _('London')),
|
---|
92 | ('GD', _('Grenada'), _("St. George's")),
|
---|
93 | ('GE', _('Georgia'), _('Tbilisi')),
|
---|
94 | ('GF', _('French Guiana'), _('Cayenne')),
|
---|
95 | ('GG', _('Guernsey'), _('Saint Peter Port')),
|
---|
96 | ('GH', _('Ghana'), _('Accra')),
|
---|
97 | ('GI', _('Gibraltar'), _('Gibraltar')),
|
---|
98 | ('GL', _('Greenland'), _('Nuuk')),
|
---|
99 | ('GM', _('Gambia'), _('Banjul')),
|
---|
100 | ('GN', _('Guinea'), _('Conakry')),
|
---|
101 | ('GP', _('Guadeloupe'), _('Basse-Terre')),
|
---|
102 | ('GQ', _('Equatorial Guinea'), _('Malabo')),
|
---|
103 | ('GR', _('Greece'), _('Athens')),
|
---|
104 | ('GS', _('South Georgia and the South Sandwich Islands'), _('Grytviken')),
|
---|
105 | ('GT', _('Guatemala'), _('Guatemala City')),
|
---|
106 | ('GU', _('Guam'), _('Hagatna')),
|
---|
107 | ('GW', _('Guinea-Bissau'), _('Bissau')),
|
---|
108 | ('GY', _('Guyana'), _('Georgetown')),
|
---|
109 | ('HK', _('Hong Kong'), _('Hong Kong')),
|
---|
110 | ('HM', _('Heard Island and McDonald Islands'), ''),
|
---|
111 | ('HN', _('Honduras'), _('Tegucigalpa')),
|
---|
112 | ('HR', _('Croatia'), _('Zagreb')),
|
---|
113 | ('HT', _('Haiti'), _('Port-au-Prince')),
|
---|
114 | ('HU', _('Hungary'), _('Budapest')),
|
---|
115 | ('ID', _('Indonesia'), _('Jakarta')),
|
---|
116 | ('IE', _('Ireland'), _('Dublin')),
|
---|
117 | ('IL', _('Israel'), _('Jerusalem')),
|
---|
118 | ('IM', _('Isle of Man'), _('Douglas')),
|
---|
119 | ('IN', _('India'), _('New Delhi')),
|
---|
120 | ('IO', _('British Indian Ocean Territory'), _('Diego Garcia')),
|
---|
121 | ('IQ', _('Iraq'), _('Iraq')),
|
---|
122 | ('IR', _('Iran'), _('Tehran')),
|
---|
123 | ('IS', _('Iceland'), _('Reykjavik')),
|
---|
124 | ('IT', _('Italy'), _('Rome')),
|
---|
125 | ('JE', _('Jersey'), _('Saint Helier')),
|
---|
126 | ('JM', _('Jamaica'), _('Kingston')),
|
---|
127 | ('JO', _('Jordan'), _('Amman')),
|
---|
128 | ('JP', _('Japan'), _('Tokyo')),
|
---|
129 | ('KE', _('Kenya'), _('Nairobi')),
|
---|
130 | ('KG', _('Kyrgyzstan'), _('Bishkek')),
|
---|
131 | ('KH', _('Cambodia'), _('Phnom Penh')),
|
---|
132 | ('KI', _('Kiribati'), _('South Tarawa')),
|
---|
133 | ('KM', _('Comoros'), _('Moroni')),
|
---|
134 | ('KN', _('Saint Kitts and Nevis'), _('Basseterre')),
|
---|
135 | ('KP', _('North Korea'), _('Pyongyang')),
|
---|
136 | ('KR', _('South Korea'), _('Seoul')),
|
---|
137 | ('KW', _('Kuwait'), _('Kuwait City')),
|
---|
138 | ('KY', _('Cayman Islands'), _('George Town')),
|
---|
139 | ('KZ', _('Kazakhstan'), _('Astana')),
|
---|
140 | ('LA', _('Laos'), _('Vientiane')),
|
---|
141 | ('LB', _('Lebanon'), _('Beirut')),
|
---|
142 | ('LC', _('Saint Lucia'), _('Castries')),
|
---|
143 | ('LI', _('Liechtenstein'), _('Vaduz')),
|
---|
144 | ('LK', _('Sri Lanka'), _('Sri Jayawardenepura Kotte')),
|
---|
145 | ('LR', _('Liberia'), _('Monrovia')),
|
---|
146 | ('LS', _('Lesotho'), _('Maseru')),
|
---|
147 | ('LT', _('Lithuania'), _('Vilnius')),
|
---|
148 | ('LU', _('Luxembourg'), _('Luxembourg City')),
|
---|
149 | ('LV', _('Latvia'), _('Riga')),
|
---|
150 | ('LY', _('Libya'), _('Tripoli')),
|
---|
151 | ('MA', _('Morocco'), _('Rabat')),
|
---|
152 | ('MC', _('Monaco'), _('Monaco')),
|
---|
153 | ('MD', _('Moldova'), _('Chisinau')),
|
---|
154 | ('ME', _('Montenegro'), _('Podgorica')),
|
---|
155 | ('MG', _('Madagascar'), _('Antananarivo')),
|
---|
156 | ('MH', _('Marshall Islands'), _('Majuro')),
|
---|
157 | ('MK', _('Macedonia'), _('Skopje')),
|
---|
158 | ('ML', _('Mali'), _('Bamako')),
|
---|
159 | ('MM', _('Myanmar'), _('Naypyidaw')),
|
---|
160 | ('MN', _('Mongolia'), _('Ulaanbaatar')),
|
---|
161 | ('MO', _('Macao'), _('Macao')),
|
---|
162 | ('MP', _('Northern Mariana Islands'), _('Saipan')),
|
---|
163 | ('MQ', _('Martinique'), _('Fort-de-France')),
|
---|
164 | ('MR', _('Mauritania'), _('Nouakchott')),
|
---|
165 | ('MS', _('Montserrat'), _('Brades')),
|
---|
166 | ('MT', _('Malta'), _('Valletta')),
|
---|
167 | ('MU', _('Mauritius'), _('Port Louis')),
|
---|
168 | ('MV', _('Maldives'), _('Male')),
|
---|
169 | ('MW', _('Malawi'), _('Lilongwe')),
|
---|
170 | ('MX', _('Mexico'), _('Mexico City')),
|
---|
171 | ('MY', _('Malaysia'), _('Putrajaya')),
|
---|
172 | ('MZ', _('Mozambique'), _('Maputo')),
|
---|
173 | ('NA', _('Namibia'), _('Windhoek')),
|
---|
174 | ('NC', _('New Caledonia'), _('Noumea')),
|
---|
175 | ('NE', _('Niger'), _('Niamey')),
|
---|
176 | ('NF', _('Norfolk Island'), _('Kingston')),
|
---|
177 | ('NG', _('Nigeria'), _('Abuja')),
|
---|
178 | ('NI', _('Nicaragua'), _('Managua')),
|
---|
179 | ('NL', _('Netherlands'), _('Amsterdam')),
|
---|
180 | ('NO', _('Norway'), _('Oslo')),
|
---|
181 | ('NP', _('Nepal'), _('Kathmandu')),
|
---|
182 | ('NR', _('Nauru'), _('Yaren')),
|
---|
183 | ('NU', _('Niue'), _('Alofi')),
|
---|
184 | ('NZ', _('New Zealand'), _('Wellington')),
|
---|
185 | ('OM', _('Oman'), _('Muscat')),
|
---|
186 | ('PA', _('Panama'), _('Panama City')),
|
---|
187 | ('PE', _('Peru'), _('Lima')),
|
---|
188 | ('PF', _('French Polynesia'), _('Papeete')),
|
---|
189 | ('PG', _('Papua New Guinea'), _('Port Moresby')),
|
---|
190 | ('PH', _('Philippines'), _('Manila')),
|
---|
191 | ('PK', _('Pakistan'), _('Islamabad')),
|
---|
192 | ('PL', _('Poland'), _('Warsaw')),
|
---|
193 | ('PM', _('Saint Pierre and Miquelon'), _('St. Pierre')),
|
---|
194 | ('PN', _('Pitcairn Islands'), _('Adamstown')),
|
---|
195 | ('PR', _('Puerto Rico'), _('San Juan')),
|
---|
196 | ('PS', _('Palestine'), _('Jerusalem')),
|
---|
197 | ('PT', _('Portugal'), _('Lisbon')),
|
---|
198 | ('PW', _('Palau'), _('Ngerulmud')),
|
---|
199 | ('PY', _('Paraguay'), _('Asuncion')),
|
---|
200 | ('QA', _('Qatar'), _('Doha')),
|
---|
201 | ('RE', _('Reunion'), _('Saint-Denis')),
|
---|
202 | ('RO', _('Romania'), _('Bucharest')),
|
---|
203 | ('RS', _('Serbia'), _('Belgrade')),
|
---|
204 | ('RU', _('Russia'), _('Moscow')),
|
---|
205 | ('RW', _('Rwanda'), _('Kigali')),
|
---|
206 | ('SA', _('Saudi Arabia'), _('Riyadh')),
|
---|
207 | ('SB', _('Solomon Islands'), _('Honiara')),
|
---|
208 | ('SC', _('Seychelles'), _('Victoria')),
|
---|
209 | ('SD', _('Sudan'), _('Khartoum')),
|
---|
210 | ('SE', _('Sweden'), _('Stockholm')),
|
---|
211 | ('SG', _('Singapore'), _('Singapore')),
|
---|
212 | ('SH', _('Saint Helena'), _('Jamestown')),
|
---|
213 | ('SI', _('Slovenia'), _('Ljubljana')),
|
---|
214 | ('SJ', _('Svalbard and Jan Mayen'), _('Longyearbyen')),
|
---|
215 | ('SK', _('Slovakia'), _('Bratislava')),
|
---|
216 | ('SL', _('Sierra Leone'), _('Freetown')),
|
---|
217 | ('SM', _('San Marino'), _('San Marino')),
|
---|
218 | ('SN', _('Senegal'), _('Dakar')),
|
---|
219 | ('SO', _('Somalia'), _('Mogadishu')),
|
---|
220 | ('SR', _('Suriname'), _('Paramaribo')),
|
---|
221 | ('ST', _('Sao Tome and Principe'), _('Sao Tome')),
|
---|
222 | ('SV', _('El Salvador'), _('San Salvador')),
|
---|
223 | ('SY', _('Syria'), _('Damascus')),
|
---|
224 | ('SZ', _('Swaziland'), _('Mbabane')),
|
---|
225 | ('TC', _('Turks and Caicos Islands'), _('Cockburn Town')),
|
---|
226 | ('TD', _('Chad'), _("N'Djamena")),
|
---|
227 | ('TF', _('French Southern Territories'), _('Port-aux-Francais')),
|
---|
228 | ('TG', _('Togo'), _('Lome')),
|
---|
229 | ('TH', _('Thailand'), _('Bangkok')),
|
---|
230 | ('TJ', _('Tajikistan'), _('Dushanbe')),
|
---|
231 | ('TK', _('Tokelau'), _('Nukunonu')),
|
---|
232 | ('TL', _('Timor-Leste'), _('Dili')),
|
---|
233 | ('TM', _('Turkmenistan'), _('Ashgabat')),
|
---|
234 | ('TN', _('Tunisia'), _('Tunis')),
|
---|
235 | ('TO', _('Tonga'), _("Nuku'alofa")),
|
---|
236 | ('TR', _('Turkey'), _('Ankara')),
|
---|
237 | ('TT', _('Trinidad and Tobago'), _('Port of Spain')),
|
---|
238 | ('TV', _('Tuvalu'), _('Funafuti')),
|
---|
239 | ('TW', _('Taiwan'), _('Taipei')),
|
---|
240 | ('TZ', _('Tanzania'), _('Dodoma')),
|
---|
241 | ('UA', _('Ukraine'), _('Kiev')),
|
---|
242 | ('UG', _('Uganda'), _('Kampala')),
|
---|
243 | ('UM', _('United States Minor Outlying Islands'), _('Wake Island')),
|
---|
244 | ('US', _('United States'), _('Washington, D.C.')),
|
---|
245 | ('UY', _('Uruguay'), _('Montevideo')),
|
---|
246 | ('UZ', _('Uzbekistan'), _('Tashkent')),
|
---|
247 | ('VA', _('Vatican City'), _('Vatican City')),
|
---|
248 | ('VC', _('Saint Vincent and the Grenadines'), _('Kingstown')),
|
---|
249 | ('VE', _('Venezuela'), _('Caracas')),
|
---|
250 | ('VG', _('Virgin Islands, British'), _('Road Town')),
|
---|
251 | ('VI', _('Virgin Islands, United States'), _('Charlotte Amalie')),
|
---|
252 | ('VN', _('Vietnam'), _('Hanoi')),
|
---|
253 | ('VU', _('Vanuatu'), _('Port Vila')),
|
---|
254 | ('WF', _('Wallis and Futuna'), _('Mata-Utu')),
|
---|
255 | ('WS', _('Samoa'), _('Apia')),
|
---|
256 | ('YE', _('Yemen'), _('Sanaa')),
|
---|
257 | ('YT', _('Mayotte'), _('Mamoudzou')),
|
---|
258 | ('ZA', _('South Africa'), _('Pretoria')),
|
---|
259 | ('ZM', _('Zambia'), _('Lusaka')),
|
---|
260 | ('ZW', _('Zimbabwe'), _('Harare')),
|
---|
261 | ('ZZ', _('Unknown or unspecified country'), ''),
|
---|
262 | )
|
---|
263 |
|
---|
264 | def sorted_countries(countries):
|
---|
265 | """
|
---|
266 | Sort countries for a given language.
|
---|
267 |
|
---|
268 | Assume ZZ is the last entry, keep it last.
|
---|
269 | """
|
---|
270 |
|
---|
271 | c = [c[0:2] for c in countries[:-1]]
|
---|
272 | c.sort(key=lambda x: x[1])
|
---|
273 | c.append(countries[-1][0:2])
|
---|
274 | return tuple(c)
|
---|
275 |
|
---|
276 | countries_choices = sorted_countries(COUNTRIES)
|
---|
277 | languages_choices = map(lambda (code, name): (code, _(name)), settings.LANGUAGES) # We have to translate names
|
---|
278 | countries_cities = dict([(c[0], c[2]) for c in COUNTRIES[:-1]])
|
---|
279 |
|
---|
280 | CITIES = sorted(countries_cities.values())
|
---|
281 |
|
---|
282 | geoip_resolver = gis_utils.GeoIP()
|
---|
283 |
|
---|
284 | def get_initial_country(request=None):
|
---|
285 | """
|
---|
286 | Returns a contry code based on a client's remote address or settings.
|
---|
287 | """
|
---|
288 |
|
---|
289 | if request:
|
---|
290 | country = geoip_resolver.country_code(request.META['REMOTE_ADDR'])
|
---|
291 | if country and country.upper() in countries_cities:
|
---|
292 | return country.upper()
|
---|
293 | return settings.DEFAULT_COUNTRY
|
---|
294 |
|
---|
295 | def get_initial_city(request=None):
|
---|
296 | """
|
---|
297 | Returns a city name based on a client's remote address or a default city from her country.
|
---|
298 | """
|
---|
299 |
|
---|
300 | # We force unicode here so that default value in a field is a proper unicode string and not a lazy one
|
---|
301 | # Otherwise psycopg2 raises an "can't adapt" error: http://code.djangoproject.com/ticket/13965
|
---|
302 |
|
---|
303 | if request:
|
---|
304 | city = geoip_resolver.city(request.META['REMOTE_ADDR'])
|
---|
305 | if city and city.get('city'):
|
---|
306 | return city['city']
|
---|
307 | return utils_encoding.force_unicode(countries_cities[get_initial_country(request)]) or getattr(settings, 'DEFUALT_CITY', None)
|
---|
308 | return getattr(settings, 'DEFUALT_CITY', None) or utils_encoding.force_unicode(countries_cities[get_initial_country()])
|
---|
309 |
|
---|
310 | def get_initial_language(request=None):
|
---|
311 | """
|
---|
312 | Returns language code based on a request or settings.
|
---|
313 | """
|
---|
314 |
|
---|
315 | if request:
|
---|
316 | return translation.get_language_from_request(request)
|
---|
317 | return settings.LANGUAGE_CODE
|
---|
318 |
|
---|
319 | class CountryField(fields.CharField):
|
---|
320 | def __init__(self, *args, **kwargs):
|
---|
321 | kwargs.setdefault('max_length', 2)
|
---|
322 | kwargs.setdefault('choices', countries_choices)
|
---|
323 | kwargs.setdefault('default', get_initial_country)
|
---|
324 |
|
---|
325 | super(fields.CharField, self).__init__(*args, **kwargs)
|
---|
326 |
|
---|
327 | def get_internal_type(self):
|
---|
328 | return "CharField"
|
---|
329 |
|
---|
330 | class CityField(fields.CharField):
|
---|
331 | def __init__(self, *args, **kwargs):
|
---|
332 | kwargs.setdefault('max_length', 150)
|
---|
333 | kwargs.setdefault('default', get_initial_city)
|
---|
334 |
|
---|
335 | super(fields.CharField, self).__init__(*args, **kwargs)
|
---|
336 |
|
---|
337 | def get_internal_type(self):
|
---|
338 | return "CharField"
|
---|
339 |
|
---|
340 | class LanguageField(fields.CharField):
|
---|
341 | def __init__(self, *args, **kwargs):
|
---|
342 | kwargs.setdefault('max_length', 5)
|
---|
343 | kwargs.setdefault('choices', languages_choices)
|
---|
344 | kwargs.setdefault('default', get_initial_language)
|
---|
345 |
|
---|
346 | super(fields.CharField, self).__init__(*args, **kwargs)
|
---|
347 |
|
---|
348 | def get_internal_type(self):
|
---|
349 | return "CharField"
|
---|