0

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.

coderboy
  • 741
  • 2
  • 17
  • 1
    You probably want something like `Product.objects.values('country__name').annotate(` to get the attribute from the country model. – AMG Mar 10 '21 at 05:03
  • could you show the models.py code where it's relevant? – shark Mar 10 '21 at 05:03
  • @AMG. I get this error after trying your solution, "django.core.exceptions.FieldError: Cannot resolve keyword 'name' into field. Join on 'country' not permitted" – coderboy Mar 10 '21 at 12:02
  • @AlexKim I have edited the question and added the models. – coderboy Mar 10 '21 at 12:16

1 Answers1

2

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]
Abdul Aziz Barkat
  • 19,475
  • 3
  • 20
  • 33
  • I tried the template own but i got this "Country Name: Number: 3 Country Name: Number: 5 Country Name: Number: 1 Country Name: Number: 1 Country Name: Number: 1 Country Name: Number: 1 Country Name: Number: 1" – coderboy Mar 10 '21 at 12:14
  • i noticed the country name is blank, why is that and also how can i get the flag attribute of the country if i need that – coderboy Mar 10 '21 at 12:14
  • 1
    @coderboy You would use either the code in the view or the one in the template. `COUNTRY_DICT[q['country']]` already turns the country code into the countries name so if you pass it to the template tag `get_country` it would not return any result to you. – Abdul Aziz Barkat Mar 10 '21 at 12:20
  • ohh, i understand better now. – coderboy Mar 10 '21 at 12:23
  • how about getting the flag. – coderboy Mar 10 '21 at 12:23
  • @coderboy If you use the template method you can simply write `{{ country.flag }}`. Or you can pass the `Country` object from the view itself. check my edit above. – Abdul Aziz Barkat Mar 10 '21 at 12:32
  • Thanks for the edit, I have been trying to get the pictorial representation of the flag gifs images but I only get the text. – coderboy Mar 10 '21 at 12:50
  • i used {{ country.flag }} and then i got "/static/flags/ar.gif" and then i used {{ country.flag_css }} and then i got "flag-sprite flag-a flag-_d" and i also tried {{ country.flag.url }} but it returned nothing instead – coderboy Mar 10 '21 at 12:53
  • This is the way i output it in my graph, "labels: [{% for country in result %}'{{ country.flag_css }}',{% endfor %}]," – coderboy Mar 10 '21 at 12:53
  • `{{ country.flag }}` would return the url for the countries flag image. So if you write `` you would get what you want. – Abdul Aziz Barkat Mar 10 '21 at 13:02
  • This is the result i get "" and so on for the rest – coderboy Mar 10 '21 at 13:17
  • Am i making some mistakes somewhere – coderboy Mar 10 '21 at 13:17