pythondjangodjango-modelsdjango-viewsdjango-countries

how to use country name as default instead of code in django-countries package


I am using an a django package called django-countries which gives me access to some countries attributes in the world such as country name, country code, country flag and some other more.

It seems the default appears to be the country code, i will like to know how to be able to use the country name instead of the default which is the country code.

models.py

from django.db import models
from django_countries.fields import CountryField

class Product(models.Model):
    name = models.CharField(max_length=36)
    price = models.PositiveIntegerField()
    country = CountryField(blank_label='(select country)')

For example in my views, i have a code like this

def analyse_market(request):
    qs = Product.objects.values('country').annotate(
        number=Count('pk')
    ).order_by('country')

    result = {
        q['country']: q['number']
        for q in qs
    }

    print(result)

    context = {"result":result}
    return render(request, 'core/analyse-market.html', context)

This return a result like this:

{'AD': 3, 'AR': 5, 'BH': 1, 'FR': 1, 'JP': 1, 'NG': 1, 'NL': 1}

In the documentation, they have different methods used such as country.name, country.code, country.flag, I have tried the country.name because it relates to what I need, but i get KeyError when using the country.name in my views.


Solution

  • The CountryField from django-countries is simply a CharField with choices. When one uses values on a field one simply gets the actual value stored in the database. You would need to turn that into what you want yourself.

    To do this in the views:

    from django_countries import countries
    
    COUNTRY_DICT = dict(countries)
    
    def analyse_market(request):
        qs = Product.objects.values('country').annotate(
            number=Count('pk')
        ).order_by('country')
    
        result = {
            COUNTRY_DICT[q['country']]: q['number']
            for q in qs
        }
    
        print(result)
    
        context = {"result":result}
        return render(request, 'core/analyse-market.html', context)
    

    To do this in the template:

    {% load countries %}
    
    {% for country_code, number in result.items %}
        {% get_country country_code as country %}
        Country Name: {{ country.name }}
        Number: {{ number }}
    {% endfor %}
    

    Edit: If you want to directly pass the Country object from the view you can do as follows:

    from django_countries.fields import Country
    
    result = {
        Country(code=q['country']): q['number']
        for q in qs
    }
    

    Note: Perhaps a list of tuples would be better for this instead? i.e.

    result = [ (Country(code=q['country']), q['number']) for q in qs]