django-countries-3.4.1/0000775000175000017500000000000012612051266015237 5ustar chrischris00000000000000django-countries-3.4.1/setup.cfg0000664000175000017500000000013012612051266017052 0ustar chrischris00000000000000[bdist_wheel] universal = 1 [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 django-countries-3.4.1/django_countries.egg-info/0000775000175000017500000000000012612051266022266 5ustar chrischris00000000000000django-countries-3.4.1/django_countries.egg-info/dependency_links.txt0000664000175000017500000000000112612051264026332 0ustar chrischris00000000000000 django-countries-3.4.1/django_countries.egg-info/not-zip-safe0000664000175000017500000000000112475432321024516 0ustar chrischris00000000000000 django-countries-3.4.1/django_countries.egg-info/PKG-INFO0000664000175000017500000004012112612051264023357 0ustar chrischris00000000000000Metadata-Version: 1.1 Name: django-countries Version: 3.4.1 Summary: Provides a country field for Django models. Home-page: https://github.com/SmileyChris/django-countries/ Author: Chris Beaven Author-email: smileychris@gmail.com License: UNKNOWN Description: ================ Django Countries ================ A Django application that provides country choices for use with forms, flag icons static files, and a country field for models. Installation ============ 1. ``pip install django-countries`` 2. Add ``django_countries`` to ``INSTALLED_APPS`` CountryField ============ A country field for Django models that provides all ISO 3166-1 countries as choices. ``CountryField`` is based on Django's ``CharField``, providing choices corresponding to the official ISO 3166-1 list of countries (with a default ``max_length`` of 2). Consider the following model using a ``CountryField``:: from django.db import models from django_countries.fields import CountryField class Person(models.Model): name = models.CharField(max_length=100) country = CountryField() Any ``Person`` instance will have a ``country`` attribute that you can use to get details of the person's country:: >>> person = Person(name='Chris', country='NZ') >>> person.country Country(code='NZ') >>> person.country.name 'New Zealand' >>> person.country.flag '/static/flags/nz.gif' This object (``person.country`` in the example) is a ``Country`` instance, which is described below. Use ``blank_label`` to set the label for the initial blank choice shown in forms:: country = CountryField(blank_label='(select country)') The ``Country`` object ---------------------- An object used to represent a country, instanciated with a two character country code. It can be compared to other objects as if it was a string containing the country code and when evaluated as text, returns the country code. name Contains the full country name. flag Contains a URL to the flag. alpha3 The three letter country code for this country. numeric The numeric country code for this country (as an integer). numeric_padded The numeric country code as a three character 0-padded string. ``CountrySelectWidget`` ----------------------- A widget is included that can show the flag image after the select box (updated with JavaScript when the selection changes). When you create your form, you can use this custom widget like normal:: from django_countries.widgets import CountrySelectWidget class PersonForm(forms.ModelForm): class Meta: model = models.Person fields = ('name', 'country') widgets = {'country': CountrySelectWidget()} Pass a ``layout`` text argument to the widget to change the positioning of the flag and widget. The default layout is:: '{widget}' Custom forms ============ If you want to use the countries in a custom form, use the following custom field to ensure the translatable strings for the country choices are left lazy until the widget renders:: from django_countries.fields import LazyTypedChoiceField class CustomForm(forms.Form): country = LazyTypedChoiceField(choices=countries) You can also use the CountrySelectWidget_ as the widget for this field if you want the flag image after the select box. Get the countries from Python ============================= Use the ``django_countries.countries`` object instance as an iterator of ISO 3166-1 country codes and names (sorted by name). For example:: >>> from django_countries import countries >>> dict(countries)['NZ'] 'New Zealand' >>> for code, name in list(countries)[:3]: ... print("{name} ({code})".format(name=name, code=code)) ... Afghanistan (AF) Åland Islands (AX) Albania (AL) Country names are translated using Django's standard ``ugettext``. If you would like to help by adding a translation, please visit https://www.transifex.com/projects/p/django-countries/ Template Tags ============= If you have your country code stored in a different place than a `CountryField` you can use the template tag to get a `Country` object and have access to all of its properties: {% load countries %} {% get_country 'BR' as country %} {{ country.name }} Customization ============= Customize the country list -------------------------- Country names are taken from the official ISO 3166-1 list. If your project requires the use of alternative names, the inclusion or exclusion of specific countries then use the ``COUNTRIES_OVERRIDE`` setting. A dictionary of names to override the defaults. Note that you will need to handle translation of customised country names. Setting a country's name to ``None`` will exclude it from the country list. For example:: COUNTRIES_OVERRIDE = { 'NZ': _('Middle Earth'), 'AU': None } If you have a specific list of countries that should be used, use ``COUNTRIES_ONLY``:: COUNTRIES_ONLY = ['NZ', 'AU'] or to specify your own country names, use a dictionary or two-tuple list (string items will use the standard country name):: COUNTRIES_ONLY = [ 'US', 'UK' ('NZ', _('Middle Earth')), ('AU', _('Desert')), ] Show certain countries first ---------------------------- Provide a list of country codes as the ``COUNTRIES_FIRST`` setting and they will be shown first in the countries list (in the order specified) before all the alphanumerically sorted countries. By default, these 'first' countries are not repeated again in the alphanumerically sorted list. If you would like them to be repeated, set the ``COUNTRIES_FIRST_REPEAT`` setting to ``True``. Finally, you can optionally separate these 'first' countries with an empty choice by providing the choice label as the ``COUNTRIES_FIRST_BREAK`` setting. Customize the flag URL ---------------------- The ``COUNTRIES_FLAG_URL`` setting can be used to set the url for the flag image assets. It defaults to:: COUNTRIES_FLAG_URL = 'flags/{code}.gif' The URL can be relative to the STATIC_URL setting, or an absolute URL. The location is parsed using Python's string formatting and is passed the following arguments: * code * code_upper For example: ``COUNTRIES_FLAG_URL = 'flags/16x10/{code_upper}.png'`` No checking is done to ensure that a static flag actually exists. Alternatively, you can specify a different URL on a specific ``CountryField``:: class Person(models.Model): name = models.CharField(max_length=100) country = CountryField( countries_flag_url='//flags.example.com/{code}.png') Single field customization -------------------------- To customize an individual field, rather than rely on project level settings, create a ``Countries`` subclass which overrides settings. To override a setting, give the class an attribute matching the lowercased setting without the ``COUNTRIES_`` prefix. Then just reference this class in a field. For example, this ``CountryField`` uses a custom country list that only includes the G8 countries:: from django_countries import Countries class G8Countries(Countries): only = [ 'CA', 'FR', 'DE', 'IT', 'JP', 'RU', 'GB', ('EU', _('European Union')) ] class Vote(models.Model): country = CountryField(countries=G8Countries) approve = models.BooleanField() Django Rest Framework field =========================== Django Countries ships with a ``CountryField`` serializer field to simplify the REST interface. For example:: class PersonSerializer(serializers.ModelSerializer): country = CountryField() class Meta: model = models.Person fields = ('name', 'email', 'country') You can optionally instanciate the field with ``countries`` with a custom Countries_ instance. .. _Countries: Single field customization_ REST output format ------------------ By default, the field will output just the country code. If you would rather have more verbose output, instanciate the field with ``country_dict=True``, which will result in the field having the following output structure:: {"code": "NZ", "name": "New Zealand"} Either the code or this dict output structure are acceptible as input irregardless of the ``country_dict`` argument's value. ========== Change Log ========== This log shows interesting changes that happen for each version, latest versions first. It can be assumed that translations have been updated each release (and any new translations added). Version 3.4 (22 October 2015) ============================= * Extend test suite to cover Django 1.8 * Fix XSS escaping issue in CountrySelectWidget * Common name changes: fix typo of Moldova, add United Kingdom * Add ``{% get_country %}`` template tag. * New ``CountryField`` Django Rest Framework serializer field. Version 3.4.1 ------------- * Fix minor packaging error. Version 3.3 (30 Mar 2015) ========================= * Add the attributes to ``Countries`` class that can override the default settings. * CountriesField can now be passed a custom countries subclass to use, which combined with the previous change allows for different country choices for different fields. * Allow ``COUNTRIES_ONLY`` to also accept just country codes in its list (rather than only two-tuples), looking up the translatable country name from the full country list. * Fix Montenegro flag size (was 12px high rather than the standard 11px). * Fix outdated ISO country name formatting for Bolivia, Gambia, Holy See, Iran, Micronesia, and Venezuela. Version 3.2 (24 Feb 2015) ========================= * Fixes initial iteration failing for a fresh ``Countries`` object. * Fix widget's flag URLs (and use ensure widget is HTML encoded safely). * Add ``countries.by_name(country, language='en')`` method, allowing lookup of a country code by its full country name. Thanks Josh Schneier. Version 3.1 (15 Jan 2015) ========================= * Start change log :) * Add a ``COUNTRIES_FIRST`` setting (and some other related ones) to allow for specific countries to be shown before the entire alphanumeric list. * Add a ``blank_label`` argument to ``CountryField`` to allow customization of the label shown in the initial blank choice shown in the select widget. Version 3.1.1 (15 Jan 2015) --------------------------- * Packaging fix (``CHANGES.rst`` wasn't in the manifest) Version 3.0 (22 Oct 2014) ========================= Django supported versions are now 1.4 (LTS) and 1.6+ * Add ``COUNTRIES_ONLY`` setting to restrict to a specific list of countries. * Optimize country name translations to avoid exessive translation calls that were causing a notable performance impact. * PyUCA integration, allowing for more accurate sorting across all locales. Also, a better sorting method when PyUCA isn't installed. * Better tests (now at 100% test coverage). * Add a ``COUNTRIES_FLAG_URL`` setting to allow custom flag urls. * Support both IOC and numeric country codes, allowing more flexible lookup of countries and specific code types. * Field descriptor now returns ``None`` if no country matches (*reverted in v3.0.1*) Version 3.0.1 (27 Oct 2014) --------------------------- * Revert descriptor to always return a Country object. * Fix the ``CountryField`` widget choices appearing empty due to a translation change in v3.0. Version 3.0.2 (29 Dec 2014) --------------------------- * Fix ``CountrySelectWidget`` failing when used with a model form that is passed a model instance. Version 2.1 (24 Mar 2014) ========================= * Add IOC (3 letter) country codes. * Fix bug when loading fixtures. Version 2.1.1 (28 Mar 2014) --------------------------- * Fix issue with translations getting evaluated early. Version 2.1.2 (28 Mar 2014) --------------------------- * Fix Python 3 compatibility. Version 2.0 (18 Feb 2014) ========================= This is the first entry to the change log. The previous version was 1.5, released 19 Nov 2012. * Optimized flag images, adding flags missing from original source. * Better storage of settings and country list. * New country list format for fields. * Better tests. * Changed ``COUNTRIES_FLAG_STATIC`` setting to ``COUNTRIES_FLAG_URL``. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Framework :: Django django-countries-3.4.1/django_countries.egg-info/top_level.txt0000664000175000017500000000002112612051264025007 0ustar chrischris00000000000000django_countries django-countries-3.4.1/django_countries.egg-info/SOURCES.txt0000664000175000017500000003076412612051266024164 0ustar chrischris00000000000000CHANGES.rst LICENSE MANIFEST.in README.rst setup.cfg setup.py tox.ini django_countries/__init__.py django_countries/conf.py django_countries/data.py django_countries/fields.py django_countries/ioc_data.py django_countries/models.py django_countries/serializer_fields.py django_countries/widgets.py django_countries.egg-info/PKG-INFO django_countries.egg-info/SOURCES.txt django_countries.egg-info/dependency_links.txt django_countries.egg-info/not-zip-safe django_countries.egg-info/top_level.txt django_countries/locale/ar/LC_MESSAGES/django.mo django_countries/locale/ar/LC_MESSAGES/django.po django_countries/locale/cs/LC_MESSAGES/django.mo django_countries/locale/cs/LC_MESSAGES/django.po django_countries/locale/de/LC_MESSAGES/django.mo django_countries/locale/de/LC_MESSAGES/django.po django_countries/locale/el/LC_MESSAGES/django.mo django_countries/locale/el/LC_MESSAGES/django.po django_countries/locale/en/LC_MESSAGES/django.mo django_countries/locale/en/LC_MESSAGES/django.po django_countries/locale/eo/LC_MESSAGES/django.mo django_countries/locale/eo/LC_MESSAGES/django.po django_countries/locale/es/LC_MESSAGES/django.mo django_countries/locale/es/LC_MESSAGES/django.po django_countries/locale/et/LC_MESSAGES/django.mo django_countries/locale/et/LC_MESSAGES/django.po django_countries/locale/fa/LC_MESSAGES/django.mo django_countries/locale/fa/LC_MESSAGES/django.po django_countries/locale/fi/LC_MESSAGES/django.mo django_countries/locale/fi/LC_MESSAGES/django.po django_countries/locale/fr/LC_MESSAGES/django.mo django_countries/locale/fr/LC_MESSAGES/django.po django_countries/locale/hr/LC_MESSAGES/django.mo django_countries/locale/hr/LC_MESSAGES/django.po django_countries/locale/it/LC_MESSAGES/django.mo django_countries/locale/it/LC_MESSAGES/django.po django_countries/locale/ja/LC_MESSAGES/django.mo django_countries/locale/ja/LC_MESSAGES/django.po django_countries/locale/nb/LC_MESSAGES/django.mo django_countries/locale/nb/LC_MESSAGES/django.po django_countries/locale/nl/LC_MESSAGES/django.mo django_countries/locale/nl/LC_MESSAGES/django.po django_countries/locale/pl/LC_MESSAGES/django.mo django_countries/locale/pl/LC_MESSAGES/django.po django_countries/locale/pt_BR/LC_MESSAGES/django.mo django_countries/locale/pt_BR/LC_MESSAGES/django.po django_countries/locale/pt_PT/LC_MESSAGES/django.mo django_countries/locale/pt_PT/LC_MESSAGES/django.po django_countries/locale/ru/LC_MESSAGES/django.mo django_countries/locale/ru/LC_MESSAGES/django.po django_countries/locale/sk/LC_MESSAGES/django.mo django_countries/locale/sk/LC_MESSAGES/django.po django_countries/locale/sv/LC_MESSAGES/django.mo django_countries/locale/sv/LC_MESSAGES/django.po django_countries/locale/tr_TR/LC_MESSAGES/django.mo django_countries/locale/tr_TR/LC_MESSAGES/django.po django_countries/locale/uk/LC_MESSAGES/django.mo django_countries/locale/uk/LC_MESSAGES/django.po django_countries/locale/zh_CN/LC_MESSAGES/django.mo django_countries/locale/zh_CN/LC_MESSAGES/django.po django_countries/static/flags/__.gif django_countries/static/flags/ad.gif django_countries/static/flags/ae.gif django_countries/static/flags/af.gif django_countries/static/flags/ag.gif django_countries/static/flags/ai.gif django_countries/static/flags/al.gif django_countries/static/flags/am.gif django_countries/static/flags/ao.gif django_countries/static/flags/aq.gif django_countries/static/flags/ar.gif django_countries/static/flags/as.gif django_countries/static/flags/at.gif django_countries/static/flags/au.gif django_countries/static/flags/aw.gif django_countries/static/flags/ax.gif django_countries/static/flags/az.gif django_countries/static/flags/ba.gif django_countries/static/flags/bb.gif django_countries/static/flags/bd.gif django_countries/static/flags/be.gif django_countries/static/flags/bf.gif django_countries/static/flags/bg.gif django_countries/static/flags/bh.gif django_countries/static/flags/bi.gif django_countries/static/flags/bj.gif django_countries/static/flags/bl.gif django_countries/static/flags/bm.gif django_countries/static/flags/bn.gif django_countries/static/flags/bo.gif django_countries/static/flags/bq.gif django_countries/static/flags/br.gif django_countries/static/flags/bs.gif django_countries/static/flags/bt.gif django_countries/static/flags/bv.gif django_countries/static/flags/bw.gif django_countries/static/flags/by.gif django_countries/static/flags/bz.gif django_countries/static/flags/ca.gif django_countries/static/flags/cc.gif django_countries/static/flags/cd.gif django_countries/static/flags/cf.gif django_countries/static/flags/cg.gif django_countries/static/flags/ch.gif django_countries/static/flags/ci.gif django_countries/static/flags/ck.gif django_countries/static/flags/cl.gif django_countries/static/flags/cm.gif django_countries/static/flags/cn.gif django_countries/static/flags/co.gif django_countries/static/flags/cr.gif django_countries/static/flags/cu.gif django_countries/static/flags/cv.gif django_countries/static/flags/cw.gif django_countries/static/flags/cx.gif django_countries/static/flags/cy.gif django_countries/static/flags/cz.gif django_countries/static/flags/de.gif django_countries/static/flags/dj.gif django_countries/static/flags/dk.gif django_countries/static/flags/dm.gif django_countries/static/flags/do.gif django_countries/static/flags/dz.gif django_countries/static/flags/ec.gif django_countries/static/flags/ee.gif django_countries/static/flags/eg.gif django_countries/static/flags/eh.gif django_countries/static/flags/er.gif django_countries/static/flags/es.gif django_countries/static/flags/et.gif django_countries/static/flags/eu.gif django_countries/static/flags/fi.gif django_countries/static/flags/fj.gif django_countries/static/flags/fk.gif django_countries/static/flags/fm.gif django_countries/static/flags/fo.gif django_countries/static/flags/fr.gif django_countries/static/flags/ga.gif django_countries/static/flags/gb.gif django_countries/static/flags/gd.gif django_countries/static/flags/ge.gif django_countries/static/flags/gf.gif django_countries/static/flags/gg.gif django_countries/static/flags/gh.gif django_countries/static/flags/gi.gif django_countries/static/flags/gl.gif django_countries/static/flags/gm.gif django_countries/static/flags/gn.gif django_countries/static/flags/gp.gif django_countries/static/flags/gq.gif django_countries/static/flags/gr.gif django_countries/static/flags/gs.gif django_countries/static/flags/gt.gif django_countries/static/flags/gu.gif django_countries/static/flags/gw.gif django_countries/static/flags/gy.gif django_countries/static/flags/hk.gif django_countries/static/flags/hm.gif django_countries/static/flags/hn.gif django_countries/static/flags/hr.gif django_countries/static/flags/ht.gif django_countries/static/flags/hu.gif django_countries/static/flags/id.gif django_countries/static/flags/ie.gif django_countries/static/flags/il.gif django_countries/static/flags/im.gif django_countries/static/flags/in.gif django_countries/static/flags/io.gif django_countries/static/flags/iq.gif django_countries/static/flags/ir.gif django_countries/static/flags/is.gif django_countries/static/flags/it.gif django_countries/static/flags/je.gif django_countries/static/flags/jm.gif django_countries/static/flags/jo.gif django_countries/static/flags/jp.gif django_countries/static/flags/ke.gif django_countries/static/flags/kg.gif django_countries/static/flags/kh.gif django_countries/static/flags/ki.gif django_countries/static/flags/km.gif django_countries/static/flags/kn.gif django_countries/static/flags/kp.gif django_countries/static/flags/kr.gif django_countries/static/flags/kw.gif django_countries/static/flags/ky.gif django_countries/static/flags/kz.gif django_countries/static/flags/la.gif django_countries/static/flags/lb.gif django_countries/static/flags/lc.gif django_countries/static/flags/li.gif django_countries/static/flags/lk.gif django_countries/static/flags/lr.gif django_countries/static/flags/ls.gif django_countries/static/flags/lt.gif django_countries/static/flags/lu.gif django_countries/static/flags/lv.gif django_countries/static/flags/ly.gif django_countries/static/flags/ma.gif django_countries/static/flags/mc.gif django_countries/static/flags/md.gif django_countries/static/flags/me.gif django_countries/static/flags/mf.gif django_countries/static/flags/mg.gif django_countries/static/flags/mh.gif django_countries/static/flags/mk.gif django_countries/static/flags/ml.gif django_countries/static/flags/mm.gif django_countries/static/flags/mn.gif django_countries/static/flags/mo.gif django_countries/static/flags/mp.gif django_countries/static/flags/mq.gif django_countries/static/flags/mr.gif django_countries/static/flags/ms.gif django_countries/static/flags/mt.gif django_countries/static/flags/mu.gif django_countries/static/flags/mv.gif django_countries/static/flags/mw.gif django_countries/static/flags/mx.gif django_countries/static/flags/my.gif django_countries/static/flags/mz.gif django_countries/static/flags/na.gif django_countries/static/flags/nc.gif django_countries/static/flags/ne.gif django_countries/static/flags/nf.gif django_countries/static/flags/ng.gif django_countries/static/flags/ni.gif django_countries/static/flags/nl.gif django_countries/static/flags/no.gif django_countries/static/flags/np.gif django_countries/static/flags/nr.gif django_countries/static/flags/nu.gif django_countries/static/flags/nz.gif django_countries/static/flags/om.gif django_countries/static/flags/pa.gif django_countries/static/flags/pe.gif django_countries/static/flags/pf.gif django_countries/static/flags/pg.gif django_countries/static/flags/ph.gif django_countries/static/flags/pk.gif django_countries/static/flags/pl.gif django_countries/static/flags/pm.gif django_countries/static/flags/pn.gif django_countries/static/flags/pr.gif django_countries/static/flags/ps.gif django_countries/static/flags/pt.gif django_countries/static/flags/pw.gif django_countries/static/flags/py.gif django_countries/static/flags/qa.gif django_countries/static/flags/re.gif django_countries/static/flags/ro.gif django_countries/static/flags/rs.gif django_countries/static/flags/ru.gif django_countries/static/flags/rw.gif django_countries/static/flags/sa.gif django_countries/static/flags/sb.gif django_countries/static/flags/sc.gif django_countries/static/flags/sd.gif django_countries/static/flags/se.gif django_countries/static/flags/sg.gif django_countries/static/flags/sh.gif django_countries/static/flags/si.gif django_countries/static/flags/sj.gif django_countries/static/flags/sk.gif django_countries/static/flags/sl.gif django_countries/static/flags/sm.gif django_countries/static/flags/sn.gif django_countries/static/flags/so.gif django_countries/static/flags/sr.gif django_countries/static/flags/ss.gif django_countries/static/flags/st.gif django_countries/static/flags/sv.gif django_countries/static/flags/sx.gif django_countries/static/flags/sy.gif django_countries/static/flags/sz.gif django_countries/static/flags/tc.gif django_countries/static/flags/td.gif django_countries/static/flags/tf.gif django_countries/static/flags/tg.gif django_countries/static/flags/th.gif django_countries/static/flags/tj.gif django_countries/static/flags/tk.gif django_countries/static/flags/tl.gif django_countries/static/flags/tm.gif django_countries/static/flags/tn.gif django_countries/static/flags/to.gif django_countries/static/flags/tr.gif django_countries/static/flags/tt.gif django_countries/static/flags/tv.gif django_countries/static/flags/tw.gif django_countries/static/flags/tz.gif django_countries/static/flags/ua.gif django_countries/static/flags/ug.gif django_countries/static/flags/um.gif django_countries/static/flags/us.gif django_countries/static/flags/uy.gif django_countries/static/flags/uz.gif django_countries/static/flags/va.gif django_countries/static/flags/vc.gif django_countries/static/flags/ve.gif django_countries/static/flags/vg.gif django_countries/static/flags/vi.gif django_countries/static/flags/vn.gif django_countries/static/flags/vu.gif django_countries/static/flags/wf.gif django_countries/static/flags/ws.gif django_countries/static/flags/ye.gif django_countries/static/flags/yt.gif django_countries/static/flags/za.gif django_countries/static/flags/zm.gif django_countries/static/flags/zw.gif django_countries/templatetags/__init__.py django_countries/templatetags/countries.py django_countries/tests/__init__.py django_countries/tests/custom_countries.py django_countries/tests/forms.py django_countries/tests/models.py django_countries/tests/settings.py django_countries/tests/settings_lts.py django_countries/tests/test_countries.py django_countries/tests/test_drf.py django_countries/tests/test_fields.py django_countries/tests/test_settings.py django_countries/tests/test_tags.py django_countries/tests/test_widgets.pydjango-countries-3.4.1/setup.py0000775000175000017500000000250412612051070016746 0ustar chrischris00000000000000#!/usr/bin/env python import codecs from setuptools import setup, find_packages def read_files(*filenames): """ Output the contents of one or more files to a single concatenated string. """ output = [] for filename in filenames: f = codecs.open(filename, encoding='utf-8') try: output.append(f.read()) finally: f.close() return '\n\n'.join(output) setup( name='django-countries', version='3.4.1', description='Provides a country field for Django models.', long_description=read_files('README.rst', 'CHANGES.rst'), author='Chris Beaven', author_email='smileychris@gmail.com', url='https://github.com/SmileyChris/django-countries/', packages=find_packages(), zip_safe=False, include_package_data=True, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Framework :: Django', ], ) django-countries-3.4.1/README.rst0000664000175000017500000002004312612047442016726 0ustar chrischris00000000000000================ Django Countries ================ A Django application that provides country choices for use with forms, flag icons static files, and a country field for models. Installation ============ 1. ``pip install django-countries`` 2. Add ``django_countries`` to ``INSTALLED_APPS`` CountryField ============ A country field for Django models that provides all ISO 3166-1 countries as choices. ``CountryField`` is based on Django's ``CharField``, providing choices corresponding to the official ISO 3166-1 list of countries (with a default ``max_length`` of 2). Consider the following model using a ``CountryField``:: from django.db import models from django_countries.fields import CountryField class Person(models.Model): name = models.CharField(max_length=100) country = CountryField() Any ``Person`` instance will have a ``country`` attribute that you can use to get details of the person's country:: >>> person = Person(name='Chris', country='NZ') >>> person.country Country(code='NZ') >>> person.country.name 'New Zealand' >>> person.country.flag '/static/flags/nz.gif' This object (``person.country`` in the example) is a ``Country`` instance, which is described below. Use ``blank_label`` to set the label for the initial blank choice shown in forms:: country = CountryField(blank_label='(select country)') The ``Country`` object ---------------------- An object used to represent a country, instanciated with a two character country code. It can be compared to other objects as if it was a string containing the country code and when evaluated as text, returns the country code. name Contains the full country name. flag Contains a URL to the flag. alpha3 The three letter country code for this country. numeric The numeric country code for this country (as an integer). numeric_padded The numeric country code as a three character 0-padded string. ``CountrySelectWidget`` ----------------------- A widget is included that can show the flag image after the select box (updated with JavaScript when the selection changes). When you create your form, you can use this custom widget like normal:: from django_countries.widgets import CountrySelectWidget class PersonForm(forms.ModelForm): class Meta: model = models.Person fields = ('name', 'country') widgets = {'country': CountrySelectWidget()} Pass a ``layout`` text argument to the widget to change the positioning of the flag and widget. The default layout is:: '{widget}' Custom forms ============ If you want to use the countries in a custom form, use the following custom field to ensure the translatable strings for the country choices are left lazy until the widget renders:: from django_countries.fields import LazyTypedChoiceField class CustomForm(forms.Form): country = LazyTypedChoiceField(choices=countries) You can also use the CountrySelectWidget_ as the widget for this field if you want the flag image after the select box. Get the countries from Python ============================= Use the ``django_countries.countries`` object instance as an iterator of ISO 3166-1 country codes and names (sorted by name). For example:: >>> from django_countries import countries >>> dict(countries)['NZ'] 'New Zealand' >>> for code, name in list(countries)[:3]: ... print("{name} ({code})".format(name=name, code=code)) ... Afghanistan (AF) Åland Islands (AX) Albania (AL) Country names are translated using Django's standard ``ugettext``. If you would like to help by adding a translation, please visit https://www.transifex.com/projects/p/django-countries/ Template Tags ============= If you have your country code stored in a different place than a `CountryField` you can use the template tag to get a `Country` object and have access to all of its properties: {% load countries %} {% get_country 'BR' as country %} {{ country.name }} Customization ============= Customize the country list -------------------------- Country names are taken from the official ISO 3166-1 list. If your project requires the use of alternative names, the inclusion or exclusion of specific countries then use the ``COUNTRIES_OVERRIDE`` setting. A dictionary of names to override the defaults. Note that you will need to handle translation of customised country names. Setting a country's name to ``None`` will exclude it from the country list. For example:: COUNTRIES_OVERRIDE = { 'NZ': _('Middle Earth'), 'AU': None } If you have a specific list of countries that should be used, use ``COUNTRIES_ONLY``:: COUNTRIES_ONLY = ['NZ', 'AU'] or to specify your own country names, use a dictionary or two-tuple list (string items will use the standard country name):: COUNTRIES_ONLY = [ 'US', 'UK' ('NZ', _('Middle Earth')), ('AU', _('Desert')), ] Show certain countries first ---------------------------- Provide a list of country codes as the ``COUNTRIES_FIRST`` setting and they will be shown first in the countries list (in the order specified) before all the alphanumerically sorted countries. By default, these 'first' countries are not repeated again in the alphanumerically sorted list. If you would like them to be repeated, set the ``COUNTRIES_FIRST_REPEAT`` setting to ``True``. Finally, you can optionally separate these 'first' countries with an empty choice by providing the choice label as the ``COUNTRIES_FIRST_BREAK`` setting. Customize the flag URL ---------------------- The ``COUNTRIES_FLAG_URL`` setting can be used to set the url for the flag image assets. It defaults to:: COUNTRIES_FLAG_URL = 'flags/{code}.gif' The URL can be relative to the STATIC_URL setting, or an absolute URL. The location is parsed using Python's string formatting and is passed the following arguments: * code * code_upper For example: ``COUNTRIES_FLAG_URL = 'flags/16x10/{code_upper}.png'`` No checking is done to ensure that a static flag actually exists. Alternatively, you can specify a different URL on a specific ``CountryField``:: class Person(models.Model): name = models.CharField(max_length=100) country = CountryField( countries_flag_url='//flags.example.com/{code}.png') Single field customization -------------------------- To customize an individual field, rather than rely on project level settings, create a ``Countries`` subclass which overrides settings. To override a setting, give the class an attribute matching the lowercased setting without the ``COUNTRIES_`` prefix. Then just reference this class in a field. For example, this ``CountryField`` uses a custom country list that only includes the G8 countries:: from django_countries import Countries class G8Countries(Countries): only = [ 'CA', 'FR', 'DE', 'IT', 'JP', 'RU', 'GB', ('EU', _('European Union')) ] class Vote(models.Model): country = CountryField(countries=G8Countries) approve = models.BooleanField() Django Rest Framework field =========================== Django Countries ships with a ``CountryField`` serializer field to simplify the REST interface. For example:: class PersonSerializer(serializers.ModelSerializer): country = CountryField() class Meta: model = models.Person fields = ('name', 'email', 'country') You can optionally instanciate the field with ``countries`` with a custom Countries_ instance. .. _Countries: Single field customization_ REST output format ------------------ By default, the field will output just the country code. If you would rather have more verbose output, instanciate the field with ``country_dict=True``, which will result in the field having the following output structure:: {"code": "NZ", "name": "New Zealand"} Either the code or this dict output structure are acceptible as input irregardless of the ``country_dict`` argument's value. django-countries-3.4.1/LICENSE0000664000175000017500000000206012475430413016244 0ustar chrischris00000000000000Copyright (c) 2010 Chris Beaven and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.django-countries-3.4.1/CHANGES.rst0000664000175000017500000000761112612051134017040 0ustar chrischris00000000000000========== Change Log ========== This log shows interesting changes that happen for each version, latest versions first. It can be assumed that translations have been updated each release (and any new translations added). Version 3.4 (22 October 2015) ============================= * Extend test suite to cover Django 1.8 * Fix XSS escaping issue in CountrySelectWidget * Common name changes: fix typo of Moldova, add United Kingdom * Add ``{% get_country %}`` template tag. * New ``CountryField`` Django Rest Framework serializer field. Version 3.4.1 ------------- * Fix minor packaging error. Version 3.3 (30 Mar 2015) ========================= * Add the attributes to ``Countries`` class that can override the default settings. * CountriesField can now be passed a custom countries subclass to use, which combined with the previous change allows for different country choices for different fields. * Allow ``COUNTRIES_ONLY`` to also accept just country codes in its list (rather than only two-tuples), looking up the translatable country name from the full country list. * Fix Montenegro flag size (was 12px high rather than the standard 11px). * Fix outdated ISO country name formatting for Bolivia, Gambia, Holy See, Iran, Micronesia, and Venezuela. Version 3.2 (24 Feb 2015) ========================= * Fixes initial iteration failing for a fresh ``Countries`` object. * Fix widget's flag URLs (and use ensure widget is HTML encoded safely). * Add ``countries.by_name(country, language='en')`` method, allowing lookup of a country code by its full country name. Thanks Josh Schneier. Version 3.1 (15 Jan 2015) ========================= * Start change log :) * Add a ``COUNTRIES_FIRST`` setting (and some other related ones) to allow for specific countries to be shown before the entire alphanumeric list. * Add a ``blank_label`` argument to ``CountryField`` to allow customization of the label shown in the initial blank choice shown in the select widget. Version 3.1.1 (15 Jan 2015) --------------------------- * Packaging fix (``CHANGES.rst`` wasn't in the manifest) Version 3.0 (22 Oct 2014) ========================= Django supported versions are now 1.4 (LTS) and 1.6+ * Add ``COUNTRIES_ONLY`` setting to restrict to a specific list of countries. * Optimize country name translations to avoid exessive translation calls that were causing a notable performance impact. * PyUCA integration, allowing for more accurate sorting across all locales. Also, a better sorting method when PyUCA isn't installed. * Better tests (now at 100% test coverage). * Add a ``COUNTRIES_FLAG_URL`` setting to allow custom flag urls. * Support both IOC and numeric country codes, allowing more flexible lookup of countries and specific code types. * Field descriptor now returns ``None`` if no country matches (*reverted in v3.0.1*) Version 3.0.1 (27 Oct 2014) --------------------------- * Revert descriptor to always return a Country object. * Fix the ``CountryField`` widget choices appearing empty due to a translation change in v3.0. Version 3.0.2 (29 Dec 2014) --------------------------- * Fix ``CountrySelectWidget`` failing when used with a model form that is passed a model instance. Version 2.1 (24 Mar 2014) ========================= * Add IOC (3 letter) country codes. * Fix bug when loading fixtures. Version 2.1.1 (28 Mar 2014) --------------------------- * Fix issue with translations getting evaluated early. Version 2.1.2 (28 Mar 2014) --------------------------- * Fix Python 3 compatibility. Version 2.0 (18 Feb 2014) ========================= This is the first entry to the change log. The previous version was 1.5, released 19 Nov 2012. * Optimized flag images, adding flags missing from original source. * Better storage of settings and country list. * New country list format for fields. * Better tests. * Changed ``COUNTRIES_FLAG_STATIC`` setting to ``COUNTRIES_FLAG_URL``. django-countries-3.4.1/django_countries/0000775000175000017500000000000012612051266020574 5ustar chrischris00000000000000django-countries-3.4.1/django_countries/ioc_data.py0000664000175000017500000000761112475430413022720 0ustar chrischris00000000000000IOC_TO_ISO = { 'AFG': 'AF', 'ALB': 'AL', 'ALG': 'DZ', 'AND': 'AD', 'ANG': 'AO', 'ANT': 'AG', 'ARG': 'AR', 'ARM': 'AM', 'ARU': 'AW', 'ASA': 'AS', 'AUS': 'AU', 'AUT': 'AT', 'AZE': 'AZ', 'BAH': 'BS', 'BAN': 'BD', 'BAR': 'BB', 'BDI': 'BI', 'BEL': 'BE', 'BEN': 'BJ', 'BER': 'BM', 'BHU': 'BT', 'BIH': 'BA', 'BIZ': 'BZ', 'BLR': 'BY', 'BOL': 'BO', 'BOT': 'BW', 'BRA': 'BR', 'BRN': 'BH', 'BRU': 'BN', 'BUL': 'BG', 'BUR': 'BF', 'CAF': 'CF', 'CAM': 'KH', 'CAN': 'CA', 'CAY': 'KY', 'CGO': 'CG', 'CHA': 'TD', 'CHI': 'CL', 'CHN': 'CN', 'CIV': 'CI', 'CMR': 'CM', 'COD': 'CD', 'COK': 'CK', 'COL': 'CO', 'COM': 'KM', 'CPV': 'CV', 'CRC': 'CR', 'CRO': 'HR', 'CUB': 'CU', 'CYP': 'CY', 'CZE': 'CZ', 'DEN': 'DK', 'DJI': 'DJ', 'DMA': 'DM', 'DOM': 'DO', 'ECU': 'EC', 'EGY': 'EG', 'ERI': 'ER', 'ESA': 'SV', 'ESP': 'ES', 'EST': 'EE', 'ETH': 'ET', 'FIJ': 'FJ', 'FIN': 'FI', 'FRA': 'FR', 'FSM': 'FM', 'GAB': 'GA', 'GAM': 'GM', 'GBR': 'GB', 'GBS': 'GW', 'GEO': 'GE', 'GEQ': 'GQ', 'GER': 'DE', 'GHA': 'GH', 'GRE': 'GR', 'GRN': 'GD', 'GUA': 'GT', 'GUI': 'GN', 'GUM': 'GU', 'GUY': 'GY', 'HAI': 'HT', 'HKG': 'HK', 'HON': 'HN', 'HUN': 'HU', 'INA': 'ID', 'IND': 'IN', 'IRI': 'IR', 'IRL': 'IE', 'IRQ': 'IQ', 'ISL': 'IS', 'ISR': 'IL', 'ISV': 'VI', 'ITA': 'IT', 'IVB': 'VG', 'JAM': 'JM', 'JOR': 'JO', 'JPN': 'JP', 'KAZ': 'KZ', 'KEN': 'KE', 'KGZ': 'KG', 'KIR': 'KI', 'KOR': 'KR', 'KSA': 'SA', 'KUW': 'KW', 'LAO': 'LA', 'LAT': 'LV', 'LBA': 'LY', 'LBR': 'LR', 'LCA': 'LC', 'LES': 'LS', 'LIB': 'LB', 'LIE': 'LI', 'LTU': 'LT', 'LUX': 'LU', 'MAD': 'MG', 'MAR': 'MA', 'MAS': 'MY', 'MAW': 'MW', 'MDA': 'MD', 'MDV': 'MV', 'MEX': 'MX', 'MGL': 'MN', 'MHL': 'MH', 'MKD': 'MK', 'MLI': 'ML', 'MLT': 'MT', 'MNE': 'ME', 'MON': 'MC', 'MOZ': 'MZ', 'MRI': 'MU', 'MTN': 'MR', 'MYA': 'MM', 'NAM': 'NA', 'NCA': 'NI', 'NED': 'NL', 'NEP': 'NP', 'NGR': 'NG', 'NIG': 'NE', 'NOR': 'NO', 'NRU': 'NR', 'NZL': 'NZ', 'OMA': 'OM', 'PAK': 'PK', 'PAN': 'PA', 'PAR': 'PY', 'PER': 'PE', 'PHI': 'PH', 'PLE': 'PS', 'PLW': 'PW', 'PNG': 'PG', 'POL': 'PL', 'POR': 'PT', 'PRK': 'KP', 'PUR': 'PR', 'QAT': 'QA', 'ROU': 'RO', 'RSA': 'ZA', 'RUS': 'RU', 'RWA': 'RW', 'SAM': 'WS', 'SEN': 'SN', 'SEY': 'SC', 'SIN': 'SG', 'SKN': 'KN', 'SLE': 'SL', 'SLO': 'SI', 'SMR': 'SM', 'SOL': 'SB', 'SOM': 'SO', 'SRB': 'RS', 'SRI': 'LK', 'STP': 'ST', 'SUD': 'SD', 'SUI': 'CH', 'SUR': 'SR', 'SVK': 'SK', 'SWE': 'SE', 'SWZ': 'SZ', 'SYR': 'SY', 'TAN': 'TZ', 'TGA': 'TO', 'THA': 'TH', 'TJK': 'TJ', 'TKM': 'TM', 'TLS': 'TL', 'TOG': 'TG', 'TPE': 'TW', 'TTO': 'TT', 'TUN': 'TN', 'TUR': 'TR', 'TUV': 'TV', 'UAE': 'AE', 'UGA': 'UG', 'UKR': 'UA', 'URU': 'UY', 'USA': 'US', 'UZB': 'UZ', 'VAN': 'VU', 'VEN': 'VE', 'VIE': 'VN', 'VIN': 'VC', 'YEM': 'YE', 'ZAM': 'ZM', 'ZIM': 'ZW', } ISO_TO_IOC = dict((iso, ioc) for ioc, iso in IOC_TO_ISO.items()) def check_ioc_countries(verbosity=1): """ Check if all IOC codes map to ISO codes correctly """ from django_countries.data import COUNTRIES if verbosity: # pragma: no cover print("Checking if all IOC codes map correctly") for key in ISO_TO_IOC: assert COUNTRIES.get(key), 'No ISO code for %s' % key if verbosity: # pragma: no cover print("Finished checking IOC codes") django-countries-3.4.1/django_countries/templatetags/0000775000175000017500000000000012612051266023266 5ustar chrischris00000000000000django-countries-3.4.1/django_countries/templatetags/countries.py0000664000175000017500000000027012572211635025655 0ustar chrischris00000000000000from django import template from django_countries.fields import Country register = template.Library() @register.assignment_tag def get_country(code): return Country(code=code) django-countries-3.4.1/django_countries/templatetags/__init__.py0000664000175000017500000000000012572211635025370 0ustar chrischris00000000000000django-countries-3.4.1/django_countries/conf.py0000664000175000017500000000477612475430413022113 0ustar chrischris00000000000000import django.conf class AppSettings(django.conf.BaseSettings): """ A holder for app-specific default settings that allows overriding via the project's settings. """ def __getattribute__(self, attr): if attr == attr.upper(): try: return getattr(django.conf.settings, attr) except AttributeError: pass return super(AppSettings, self).__getattribute__(attr) class Settings(AppSettings): COUNTRIES_FLAG_URL = 'flags/{code}.gif' """ The URL for a flag. It can either be relative to the static url, or an absolute url. The location is parsed using Python's string formatting and is passed the following arguments: * code * code_upper For example: ``COUNTRIES_FLAG_URL = 'flags/16x10/{code_upper}.png'`` """ COUNTRIES_COMMON_NAMES = True """ Whether to use the common names for some countries, as opposed to the official ISO name. Some examples: "Bolivia" instead of "Bolivia, Plurinational State of" "South Korea" instead of "Korea (the Republic of)" "Taiwan" instead of "Taiwan (Province of China)" """ COUNTRIES_OVERRIDE = {} """ A dictionary of names to override the defaults. Note that you will need to handle translation of customised country names. Setting a country's name to ``None`` will exclude it from the country list. For example:: COUNTRIES_OVERRIDE = { 'NZ': _('Middle Earth'), 'AU': None } """ COUNTRIES_ONLY = {} """ Similar to COUNTRIES_OVERRIDE A dictionary of names to include in selection. Note that you will need to handle translation of customised country names. For example:: COUNTRIES_ONLY = { 'NZ': _('Middle Earth'), 'AU': _('Desert'), } """ COUNTRIES_FIRST = [] """ Countries matching the country codes provided in this list will be shown first in the countries list (in the order specified) before all the alphanumerically sorted countries. """ COUNTRIES_FIRST_REPEAT = False """ Countries listed in :attr:`COUNTRIES_FIRST` will be repeated again in the alphanumerically sorted list if set to ``True``. """ COUNTRIES_FIRST_BREAK = None """ Countries listed in :attr:`COUNTRIES_FIRST` will be followed by a null choice with this title (if set) before all the alphanumerically sorted countries. """ settings = Settings() django-countries-3.4.1/django_countries/tests/0000775000175000017500000000000012612051266021736 5ustar chrischris00000000000000django-countries-3.4.1/django_countries/tests/settings_lts.py0000664000175000017500000000023012475430413025027 0ustar chrischris00000000000000""" Allow Django 1.4 to use the same test discovery runner method. """ from .settings import * # NOQA TEST_RUNNER = 'discover_runner.DiscoverRunner' django-countries-3.4.1/django_countries/tests/settings.py0000664000175000017500000000050512475430413024152 0ustar chrischris00000000000000SECRET_KEY = 'test' INSTALLED_APPS = ( 'django_countries', 'django_countries.tests', ) DATABASES = { 'default': {'ENGINE': 'django.db.backends.sqlite3'} } STATIC_URL = '/static-assets/' MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', ) django-countries-3.4.1/django_countries/tests/test_tags.py0000664000175000017500000000217112572211635024311 0ustar chrischris00000000000000from django.template import Template, Context from django.test import TestCase from django.utils import translation class TestCountriesTags(TestCase): TEMPLATE_COUNTRY = Template( "{% load countries %}{% get_country code as country %}{{ country }}") TEMPLATE_NAME = Template( "{% load countries %}{% get_country code as country %}" "{{ country.name }}") def test_country(self): rendered = self.TEMPLATE_COUNTRY.render(Context({'code': 'BR'})) self.assertEqual(rendered, 'BR') def test_country_name(self): rendered = self.TEMPLATE_NAME.render(Context({'code': 'BR'})) self.assertEqual(rendered, 'Brazil') def test_country_name_translated(self): with translation.override('pt-BR'): rendered = self.TEMPLATE_NAME.render(Context({'code': 'BR'})) self.assertEqual(rendered, 'Brasil') def test_wrong_code(self): rendered = self.TEMPLATE_COUNTRY.render(Context({'code': 'XX'})) self.assertEqual(rendered, 'XX') rendered = self.TEMPLATE_NAME.render(Context({'code': 'XX'})) self.assertEqual(rendered, '') django-countries-3.4.1/django_countries/tests/test_fields.py0000664000175000017500000002420712612047442024623 0ustar chrischris00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals import django from django.forms import Select from django.forms.models import modelform_factory from django.test import TestCase from django.utils import translation from django.utils.encoding import force_text try: from unittest import skipIf except ImportError: from django.utils.unittest import skipIf from django_countries import fields, countries from django_countries.tests import forms, custom_countries from django_countries.tests.models import Person, AllowNull, en_zed skipUnlessLegacy = skipIf( django.VERSION >= (1, 5), "Legacy tests only necessary in Django < 1.5") class TestCountryField(TestCase): def test_logic(self): person = Person(name='Chris Beaven', country='NZ') self.assertEqual(person.country, 'NZ') self.assertNotEqual(person.country, 'ZZ') self.assertTrue(person.country) person.country = '' self.assertFalse(person.country) def test_only_from_instance(self): self.assertRaises(AttributeError, lambda: Person.country) @skipIf( django.VERSION < (1, 7), "Field.deconstruct introduced in Django 1.7") def test_deconstruct(self): field = Person._meta.get_field('country') self.assertEqual( field.deconstruct(), ('country', 'django_countries.fields.CountryField', [], {'max_length': 2})) def test_text(self): person = Person(name='Chris Beaven', country='NZ') self.assertEqual(force_text(person.country), 'NZ') def test_name(self): person = Person(name='Chris Beaven', country='NZ') self.assertEqual(person.country.name, 'New Zealand') def test_flag(self): person = Person(name='Chris Beaven', country='NZ') with self.settings(STATIC_URL='/static-assets/'): self.assertEqual( person.country.flag, '/static-assets/flags/nz.gif') def test_custom_field_flag_url(self): person = Person(name='Chris Beaven', country='NZ', other_country='US') self.assertEqual( person.other_country.flag, '//flags.example.com/us.gif') def test_COUNTRIES_FLAG_URL_setting(self): # Custom relative url person = Person(name='Chris Beaven', country='NZ') with self.settings(COUNTRIES_FLAG_URL='img/flag-{code_upper}.png', STATIC_URL='/static-assets/'): self.assertEqual( person.country.flag, '/static-assets/img/flag-NZ.png') # Custom absolute url with self.settings(COUNTRIES_FLAG_URL='https://flags.example.com/' '{code_upper}.PNG'): self.assertEqual( person.country.flag, 'https://flags.example.com/NZ.PNG') def test_blank(self): person = Person.objects.create(name='The Outsider') self.assertEqual(person.country.code, '') person = Person.objects.get(pk=person.pk) self.assertEqual(person.country.code, '') def test_null(self): person = AllowNull.objects.create(country=None) self.assertIsNone(person.country.code) person = AllowNull.objects.get(pk=person.pk) self.assertIsNone(person.country.code) def test_len(self): person = Person(name='Chris Beaven', country='NZ') self.assertEqual(len(person.country), 2) person = Person(name='The Outsider', country=None) self.assertEqual(len(person.country), 0) def test_lookup_text(self): Person.objects.create(name='Chris Beaven', country='NZ') Person.objects.create(name='Pavlova', country='NZ') Person.objects.create(name='Killer everything', country='AU') lookup = Person.objects.filter(country='NZ') names = lookup.order_by('name').values_list('name', flat=True) self.assertEqual(list(names), ['Chris Beaven', 'Pavlova']) def test_lookup_country(self): Person.objects.create(name='Chris Beaven', country='NZ') Person.objects.create(name='Pavlova', country='NZ') Person.objects.create(name='Killer everything', country='AU') oz = fields.Country(code='AU', flag_url='') lookup = Person.objects.filter(country=oz) names = lookup.values_list('name', flat=True) self.assertEqual(list(names), ['Killer everything']) def test_save_empty_country(self): Person.objects.create(name='The Outsider') person = Person.objects.get() self.assertEqual(person.country.code, '') def test_create_modelform(self): Form = modelform_factory(Person, fields=['country']) form_field = Form().fields['country'] self.assertTrue(isinstance(form_field.widget, Select)) def test_render_form(self): Form = modelform_factory(Person, fields=['country']) Form().as_p() def test_custom_country(self): self.assertEqual( list(Person._meta.get_field('fantasy_countries').choices), [('NV', 'Neverland'), ('NZ', 'New Zealand')]) @skipIf( django.VERSION < (1, 7), "Field.deconstruct introduced in Django 1.7") def test_custom_country_deconstruct(self): field = Person._meta.get_field('fantasy_countries') self.assertEqual( field.deconstruct(), ( 'fantasy_countries', 'django_countries.fields.CountryField', [], { 'countries': custom_countries.FantasyCountries, 'max_length': 2 } )) class TestCountryObject(TestCase): def test_hash(self): country = fields.Country(code='XX', flag_url='') self.assertEqual(hash(country), hash('XX')) def test_repr(self): country1 = fields.Country(code='XX') country2 = fields.Country(code='XX', flag_url='') country3 = fields.Country(code='XX', str_attr='name') self.assertEqual( repr(country1), 'Country(code={0})'.format(repr('XX'))) self.assertEqual( repr(country2), 'Country(code={0}, flag_url={1})'.format(repr('XX'), repr(''))) self.assertEqual( repr(country3), 'Country(code={0}, str_attr={1})'.format(repr('XX'), repr('name'))) def test_str(self): country = fields.Country(code='NZ') self.assertEqual('%s' % country, 'NZ') def test_str_attr(self): country = fields.Country(code='NZ', str_attr='name') self.assertEqual('%s' % country, 'New Zealand') def test_flag_on_empty_code(self): country = fields.Country(code='', flag_url='') self.assertEqual(country.flag, '') def test_ioc_code(self): country = fields.Country(code='NL', flag_url='') self.assertEqual(country.ioc_code, 'NED') def test_country_from_ioc_code(self): country = fields.Country.country_from_ioc('NED') self.assertEqual(country, fields.Country('NL', flag_url='')) def test_country_from_blank_ioc_code(self): country = fields.Country.country_from_ioc('') self.assertIsNone(country) def test_country_from_nonexistence_ioc_code(self): country = fields.Country.country_from_ioc('XXX') self.assertIsNone(country) def test_alpha3(self): country = fields.Country(code='BN') self.assertEqual(country.alpha3, 'BRN') def test_alpha3_invalid(self): country = fields.Country(code='XX') self.assertEqual(country.alpha3, '') def test_numeric(self): country = fields.Country(code='BN') self.assertEqual(country.numeric, 96) def test_numeric_padded(self): country = fields.Country(code='AL') self.assertEqual(country.numeric_padded, '008') country = fields.Country(code='BN') self.assertEqual(country.numeric_padded, '096') country = fields.Country(code='NZ') self.assertEqual(country.numeric_padded, '554') def test_numeric_invalid(self): country = fields.Country(code='XX') self.assertEqual(country.numeric, None) def test_numeric_padded_invalid(self): country = fields.Country(code='XX') self.assertEqual(country.numeric_padded, None) def test_empty_flag_url(self): country = fields.Country(code='XX', flag_url='') self.assertEqual(country.flag, '') class TestModelForm(TestCase): def test_translated_choices(self): lang = translation.get_language() translation.activate('eo') form = forms.PersonForm() try: # This is just to prove that the language changed. self.assertEqual(list(countries)[0][1], 'Afganio') # If the choices aren't lazy, this wouldn't be translated. It's the # second choice because the first one is the initial blank option. self.assertEqual( form.fields['country'].choices[1][1], 'Afganio') self.assertEqual( form.fields['country'].widget.choices[1][1], 'Afganio') finally: translation.activate(lang) def test_blank_choice(self): form = forms.PersonForm() self.assertEqual(form.fields['country'].choices[0], ('', '---------')) def test_no_blank_choice(self): form = forms.PersonForm() self.assertEqual( form.fields['favourite_country'].choices[0], ('AF', 'Afghanistan')) def test_blank_choice_label(self): form = forms.AllowNullForm() self.assertEqual( form.fields['country'].choices[0], ('', '(select country)')) @skipUnlessLegacy def test_legacy_default(self): self.assertEqual( forms.LegacyForm.base_fields['default'].initial, 'AU') @skipUnlessLegacy def test_legacy_default_callable(self): self.assertEqual( forms.LegacyForm.base_fields['default_callable'].initial, en_zed) form = forms.LegacyForm() self.assertEqual(form['default_callable'].value(), 'NZ') @skipUnlessLegacy def test_legacy_empty_value(self): self.assertEqual( forms.LegacyForm.base_fields['default'].empty_value, None) self.assertEqual( forms.LegacyForm.base_fields['default_callable'].empty_value, '') django-countries-3.4.1/django_countries/tests/test_widgets.py0000664000175000017500000000415712475430413025026 0ustar chrischris00000000000000from __future__ import unicode_literals try: from urllib import parse as urlparse except ImportError: import urlparse # Python 2 from django.forms.models import modelform_factory from django.test import TestCase from django.utils import safestring from django.utils.html import escape from django_countries import widgets, countries, fields from django_countries.conf import settings from django_countries.tests.models import Person class TestCountrySelectWidget(TestCase): def setUp(self): del countries.countries self.Form = modelform_factory( Person, fields=['country'], widgets={'country': widgets.CountrySelectWidget}) def tearDown(self): del countries.countries def test_not_default_widget(self): Form = modelform_factory(Person, fields=['country']) widget = Form().fields['country'].widget self.assertFalse(isinstance(widget, widgets.CountrySelectWidget)) def test_render_contains_flag_url(self): with self.settings(COUNTRIES_ONLY={'AU': 'Desert'}): html = self.Form().as_p() self.assertIn(escape(urlparse.urljoin( settings.STATIC_URL, settings.COUNTRIES_FLAG_URL)), html) def test_render(self): with self.settings(COUNTRIES_ONLY={'AU': 'Desert'}): html = self.Form().as_p() self.assertIn(fields.Country('__').flag, html) self.assertNotIn(fields.Country('AU').flag, html) def test_render_initial(self): with self.settings(COUNTRIES_ONLY={'AU': 'Desert'}): html = self.Form(initial={'country': 'AU'}).as_p() self.assertIn(fields.Country('AU').flag, html) self.assertNotIn(fields.Country('__').flag, html) def test_render_escaping(self): output = widgets.CountrySelectWidget().render('test', '