CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-django-countries

A Django application that provides country choices for use with forms, flag icons static files, and a country field for models.

Pending
Overview
Eval results
Files

graphql-support.mddocs/

GraphQL Support

GraphQL type definitions for country data integration with graphene-django. The GraphQL support provides structured country information for GraphQL APIs with complete country metadata access.

Requirements

GraphQL support requires the graphene-django package:

pip install graphene-django

Capabilities

Country GraphQL Type

GraphQL ObjectType for representing country data with all ISO 3166-1 codes and names.

import graphene

class Country(graphene.ObjectType):
    """GraphQL type for country representation."""
    
    name = graphene.String(description="Country name")
    code = graphene.String(description="ISO 3166-1 two character country code")  
    alpha3 = graphene.String(description="ISO 3166-1 three character country code")
    numeric = graphene.Int(description="ISO 3166-1 numeric country code")
    ioc_code = graphene.String(description="International Olympic Committee country code")

    @staticmethod
    def resolve_name(country, info):
        """Resolve country name."""
        return country.name

    @staticmethod  
    def resolve_code(country, info):
        """Resolve country code."""
        return country.code

    @staticmethod
    def resolve_alpha3(country, info):
        """Resolve alpha3 country code."""
        return country.alpha3

    @staticmethod
    def resolve_numeric(country, info):
        """Resolve numeric country code."""
        return country.numeric

    @staticmethod
    def resolve_ioc_code(country, info):
        """Resolve IOC country code."""
        return country.ioc_code

Usage Examples

Basic Schema Integration

import graphene
from django_countries.graphql.types import Country
from django_countries import countries
from django_countries.fields import Country as CountryObject

class Query(graphene.ObjectType):
    country = graphene.Field(Country, code=graphene.String())
    countries = graphene.List(Country)
    
    def resolve_country(self, info, code=None):
        """Get single country by code."""
        if code:
            country_obj = CountryObject(code=code)
            if country_obj.code:  # Validate country exists
                return country_obj
        return None
    
    def resolve_countries(self, info):
        """Get all countries."""
        return [CountryObject(code=country.code) for country in countries]

schema = graphene.Schema(query=Query)

Model Integration

import graphene
from graphene_django import DjangoObjectType
from django_countries.graphql.types import Country
from myapp.models import Person

class PersonType(DjangoObjectType):
    """GraphQL type for Person model with country field."""
    
    country = graphene.Field(Country)
    
    class Meta:
        model = Person
        fields = ['id', 'name', 'country']
    
    def resolve_country(self, info):
        """Resolve country field to Country GraphQL type."""
        return self.country  # CountryField automatically provides Country object

class Query(graphene.ObjectType):
    person = graphene.Field(PersonType, id=graphene.ID())
    people = graphene.List(PersonType)
    
    def resolve_person(self, info, id):
        try:
            return Person.objects.get(id=id)
        except Person.DoesNotExist:
            return None
            
    def resolve_people(self, info):
        return Person.objects.all()

Advanced Queries

import graphene
from django_countries.graphql.types import Country
from django_countries import countries
from django_countries.fields import Country as CountryObject

class CountryQueries(graphene.ObjectType):
    """Extended country queries."""
    
    country = graphene.Field(
        Country, 
        code=graphene.String(description="Country code (alpha2, alpha3, or numeric)")
    )
    
    countries = graphene.List(
        Country,
        name_contains=graphene.String(description="Filter by name containing text"),
        first=graphene.Int(description="Limit number of results")
    )
    
    countries_by_region = graphene.List(
        Country,
        region=graphene.String(description="Filter by region/continent")
    )
    
    def resolve_country(self, info, code):
        """Get country by any code format."""
        country_obj = CountryObject(code=code)
        return country_obj if country_obj.code else None
    
    def resolve_countries(self, info, name_contains=None, first=None):
        """Get countries with optional filtering."""
        country_list = []
        
        for country_tuple in countries:
            country_obj = CountryObject(code=country_tuple.code)
            
            # Filter by name if specified
            if name_contains and name_contains.lower() not in country_obj.name.lower():
                continue
                
            country_list.append(country_obj)
            
            # Limit results if specified
            if first and len(country_list) >= first:
                break
        
        return country_list
    
    def resolve_countries_by_region(self, info, region):
        """Get countries by region (example implementation)."""
        # This would require additional regional data
        # Implementation depends on your regional classification needs
        european_countries = ["DE", "FR", "IT", "ES", "NL", "BE", "AT", "PT"]
        
        if region.lower() == "europe":
            return [CountryObject(code=code) for code in european_countries]
        
        return []

# Add to main query
class Query(CountryQueries, graphene.ObjectType):
    pass

GraphQL Schema Examples

# Get single country
query GetCountry {
  country(code: "US") {
    name
    code
    alpha3
    numeric
    iocCode
  }
}

# Get all countries
query GetAllCountries {
  countries {
    name
    code
    alpha3
  }
}

# Get countries with filtering
query GetFilteredCountries {
  countries(nameContains: "United", first: 5) {
    name
    code
  }
}

# Get person with country details
query GetPersonWithCountry {
  person(id: "1") {
    name
    country {
      name
      code
      alpha3
      flag
    }
  }
}

# Get all people with their countries
query GetPeopleWithCountries {
  people {
    name
    country {
      name
      code
    }
  }
}

Response Examples

// Single country query response
{
  "data": {
    "country": {
      "name": "United States",
      "code": "US",
      "alpha3": "USA", 
      "numeric": 840,
      "iocCode": "USA"
    }
  }
}

// Countries list response
{
  "data": {
    "countries": [
      {
        "name": "Afghanistan",
        "code": "AF",
        "alpha3": "AFG"
      },
      {
        "name": "Albania", 
        "code": "AL",
        "alpha3": "ALB"
      }
    ]
  }
}

// Person with country response
{
  "data": {
    "person": {
      "name": "John Doe",
      "country": {
        "name": "United States",
        "code": "US",
        "alpha3": "USA"
      }
    }
  }
}

Custom Country Extensions

import graphene
from django_countries.graphql.types import Country as BaseCountry
from django_countries.fields import Country as CountryObject

class ExtendedCountry(BaseCountry):
    """Extended country type with additional fields."""
    
    flag_url = graphene.String(description="Flag image URL")
    region = graphene.String(description="Geographic region")
    
    @staticmethod
    def resolve_flag_url(country, info):
        """Resolve flag URL."""
        return country.flag
    
    @staticmethod  
    def resolve_region(country, info):
        """Resolve geographic region (custom implementation)."""
        # Example regional mapping
        regions = {
            "US": "North America",
            "CA": "North America", 
            "MX": "North America",
            "DE": "Europe",
            "FR": "Europe",
            "GB": "Europe"
        }
        return regions.get(country.code, "Unknown")

class ExtendedQuery(graphene.ObjectType):
    country = graphene.Field(ExtendedCountry, code=graphene.String())
    
    def resolve_country(self, info, code):
        country_obj = CountryObject(code=code)
        return country_obj if country_obj.code else None

Mutations

import graphene
from django_countries.graphql.types import Country
from myapp.models import Person

class UpdatePersonCountry(graphene.Mutation):
    """Mutation to update person's country."""
    
    class Arguments:
        person_id = graphene.ID(required=True)
        country_code = graphene.String(required=True)
    
    person = graphene.Field(PersonType)
    success = graphene.Boolean()
    
    def mutate(self, info, person_id, country_code):
        try:
            person = Person.objects.get(id=person_id)
            person.country = country_code
            person.save()
            return UpdatePersonCountry(person=person, success=True)
        except Person.DoesNotExist:
            return UpdatePersonCountry(person=None, success=False)

class Mutation(graphene.ObjectType):
    update_person_country = UpdatePersonCountry.Field()

# Mutation example
"""
mutation UpdateCountry {
  updatePersonCountry(personId: "1", countryCode: "CA") {
    success
    person {
      name
      country {
        name
        code
      }
    }
  }
}
"""

Subscriptions

import graphene
from channels_graphql_ws import Subscription
from django_countries.graphql.types import Country
from myapp.models import Person

class CountryUpdates(Subscription):
    """Subscription for country-related updates."""
    
    country_updated = graphene.Field(Country)
    
    def subscribe(self, info, **kwargs):
        """Subscribe to country updates."""
        return ["country_updates"]
    
    def publish(self, info, **kwargs):
        """Publish country update."""
        return CountryUpdates(country_updated=kwargs.get("country"))

class Subscription(graphene.ObjectType):
    country_updates = CountryUpdates.Field()

Error Handling

import graphene
from django_countries.graphql.types import Country
from django_countries.fields import Country as CountryObject

class CountryError(graphene.ObjectType):
    """Error type for country operations."""
    message = graphene.String()
    code = graphene.String()

class CountryResult(graphene.Union):
    """Union type for country results."""
    class Meta:
        types = (Country, CountryError)

class SafeQuery(graphene.ObjectType):
    country = graphene.Field(CountryResult, code=graphene.String())
    
    def resolve_country(self, info, code):
        """Get country with error handling."""
        try:
            country_obj = CountryObject(code=code)
            if country_obj.code:
                return country_obj
            else:
                return CountryError(
                    message=f"Country with code '{code}' not found",
                    code="COUNTRY_NOT_FOUND"
                )
        except Exception as e:
            return CountryError(
                message=f"Error retrieving country: {str(e)}",
                code="COUNTRY_ERROR"
            )

Performance Optimization

import graphene
from django.utils.functional import cached_property
from django_countries.graphql.types import Country
from django_countries import countries

class OptimizedQuery(graphene.ObjectType):
    """Optimized country queries with caching."""
    
    @cached_property
    def _countries_cache(self):
        """Cache countries list for better performance."""
        return {country.code: country for country in countries}
    
    country = graphene.Field(Country, code=graphene.String())
    countries = graphene.List(Country)
    
    def resolve_country(self, info, code):
        """Optimized country lookup."""
        country_tuple = self._countries_cache.get(code.upper())
        if country_tuple:
            return CountryObject(code=country_tuple.code)
        return None
    
    def resolve_countries(self, info):
        """Optimized countries list."""
        # Use cached data to avoid repeated database/memory access
        return [CountryObject(code=ct.code) for ct in self._countries_cache.values()]

Install with Tessl CLI

npx tessl i tessl/pypi-django-countries

docs

admin-integration.md

countries-registry.md

django-rest-framework.md

form-fields-widgets.md

graphql-support.md

index.md

model-fields.md

template-tags.md

tile.json