0
# GraphQL Support
1
2
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.
3
4
## Requirements
5
6
GraphQL support requires the `graphene-django` package:
7
8
```bash
9
pip install graphene-django
10
```
11
12
## Capabilities
13
14
### Country GraphQL Type
15
16
GraphQL ObjectType for representing country data with all ISO 3166-1 codes and names.
17
18
```python { .api }
19
import graphene
20
21
class Country(graphene.ObjectType):
22
"""GraphQL type for country representation."""
23
24
name = graphene.String(description="Country name")
25
code = graphene.String(description="ISO 3166-1 two character country code")
26
alpha3 = graphene.String(description="ISO 3166-1 three character country code")
27
numeric = graphene.Int(description="ISO 3166-1 numeric country code")
28
ioc_code = graphene.String(description="International Olympic Committee country code")
29
30
@staticmethod
31
def resolve_name(country, info):
32
"""Resolve country name."""
33
return country.name
34
35
@staticmethod
36
def resolve_code(country, info):
37
"""Resolve country code."""
38
return country.code
39
40
@staticmethod
41
def resolve_alpha3(country, info):
42
"""Resolve alpha3 country code."""
43
return country.alpha3
44
45
@staticmethod
46
def resolve_numeric(country, info):
47
"""Resolve numeric country code."""
48
return country.numeric
49
50
@staticmethod
51
def resolve_ioc_code(country, info):
52
"""Resolve IOC country code."""
53
return country.ioc_code
54
```
55
56
## Usage Examples
57
58
### Basic Schema Integration
59
60
```python
61
import graphene
62
from django_countries.graphql.types import Country
63
from django_countries import countries
64
from django_countries.fields import Country as CountryObject
65
66
class Query(graphene.ObjectType):
67
country = graphene.Field(Country, code=graphene.String())
68
countries = graphene.List(Country)
69
70
def resolve_country(self, info, code=None):
71
"""Get single country by code."""
72
if code:
73
country_obj = CountryObject(code=code)
74
if country_obj.code: # Validate country exists
75
return country_obj
76
return None
77
78
def resolve_countries(self, info):
79
"""Get all countries."""
80
return [CountryObject(code=country.code) for country in countries]
81
82
schema = graphene.Schema(query=Query)
83
```
84
85
### Model Integration
86
87
```python
88
import graphene
89
from graphene_django import DjangoObjectType
90
from django_countries.graphql.types import Country
91
from myapp.models import Person
92
93
class PersonType(DjangoObjectType):
94
"""GraphQL type for Person model with country field."""
95
96
country = graphene.Field(Country)
97
98
class Meta:
99
model = Person
100
fields = ['id', 'name', 'country']
101
102
def resolve_country(self, info):
103
"""Resolve country field to Country GraphQL type."""
104
return self.country # CountryField automatically provides Country object
105
106
class Query(graphene.ObjectType):
107
person = graphene.Field(PersonType, id=graphene.ID())
108
people = graphene.List(PersonType)
109
110
def resolve_person(self, info, id):
111
try:
112
return Person.objects.get(id=id)
113
except Person.DoesNotExist:
114
return None
115
116
def resolve_people(self, info):
117
return Person.objects.all()
118
```
119
120
### Advanced Queries
121
122
```python
123
import graphene
124
from django_countries.graphql.types import Country
125
from django_countries import countries
126
from django_countries.fields import Country as CountryObject
127
128
class CountryQueries(graphene.ObjectType):
129
"""Extended country queries."""
130
131
country = graphene.Field(
132
Country,
133
code=graphene.String(description="Country code (alpha2, alpha3, or numeric)")
134
)
135
136
countries = graphene.List(
137
Country,
138
name_contains=graphene.String(description="Filter by name containing text"),
139
first=graphene.Int(description="Limit number of results")
140
)
141
142
countries_by_region = graphene.List(
143
Country,
144
region=graphene.String(description="Filter by region/continent")
145
)
146
147
def resolve_country(self, info, code):
148
"""Get country by any code format."""
149
country_obj = CountryObject(code=code)
150
return country_obj if country_obj.code else None
151
152
def resolve_countries(self, info, name_contains=None, first=None):
153
"""Get countries with optional filtering."""
154
country_list = []
155
156
for country_tuple in countries:
157
country_obj = CountryObject(code=country_tuple.code)
158
159
# Filter by name if specified
160
if name_contains and name_contains.lower() not in country_obj.name.lower():
161
continue
162
163
country_list.append(country_obj)
164
165
# Limit results if specified
166
if first and len(country_list) >= first:
167
break
168
169
return country_list
170
171
def resolve_countries_by_region(self, info, region):
172
"""Get countries by region (example implementation)."""
173
# This would require additional regional data
174
# Implementation depends on your regional classification needs
175
european_countries = ["DE", "FR", "IT", "ES", "NL", "BE", "AT", "PT"]
176
177
if region.lower() == "europe":
178
return [CountryObject(code=code) for code in european_countries]
179
180
return []
181
182
# Add to main query
183
class Query(CountryQueries, graphene.ObjectType):
184
pass
185
```
186
187
### GraphQL Schema Examples
188
189
```graphql
190
# Get single country
191
query GetCountry {
192
country(code: "US") {
193
name
194
code
195
alpha3
196
numeric
197
iocCode
198
}
199
}
200
201
# Get all countries
202
query GetAllCountries {
203
countries {
204
name
205
code
206
alpha3
207
}
208
}
209
210
# Get countries with filtering
211
query GetFilteredCountries {
212
countries(nameContains: "United", first: 5) {
213
name
214
code
215
}
216
}
217
218
# Get person with country details
219
query GetPersonWithCountry {
220
person(id: "1") {
221
name
222
country {
223
name
224
code
225
alpha3
226
flag
227
}
228
}
229
}
230
231
# Get all people with their countries
232
query GetPeopleWithCountries {
233
people {
234
name
235
country {
236
name
237
code
238
}
239
}
240
}
241
```
242
243
### Response Examples
244
245
```json
246
// Single country query response
247
{
248
"data": {
249
"country": {
250
"name": "United States",
251
"code": "US",
252
"alpha3": "USA",
253
"numeric": 840,
254
"iocCode": "USA"
255
}
256
}
257
}
258
259
// Countries list response
260
{
261
"data": {
262
"countries": [
263
{
264
"name": "Afghanistan",
265
"code": "AF",
266
"alpha3": "AFG"
267
},
268
{
269
"name": "Albania",
270
"code": "AL",
271
"alpha3": "ALB"
272
}
273
]
274
}
275
}
276
277
// Person with country response
278
{
279
"data": {
280
"person": {
281
"name": "John Doe",
282
"country": {
283
"name": "United States",
284
"code": "US",
285
"alpha3": "USA"
286
}
287
}
288
}
289
}
290
```
291
292
### Custom Country Extensions
293
294
```python
295
import graphene
296
from django_countries.graphql.types import Country as BaseCountry
297
from django_countries.fields import Country as CountryObject
298
299
class ExtendedCountry(BaseCountry):
300
"""Extended country type with additional fields."""
301
302
flag_url = graphene.String(description="Flag image URL")
303
region = graphene.String(description="Geographic region")
304
305
@staticmethod
306
def resolve_flag_url(country, info):
307
"""Resolve flag URL."""
308
return country.flag
309
310
@staticmethod
311
def resolve_region(country, info):
312
"""Resolve geographic region (custom implementation)."""
313
# Example regional mapping
314
regions = {
315
"US": "North America",
316
"CA": "North America",
317
"MX": "North America",
318
"DE": "Europe",
319
"FR": "Europe",
320
"GB": "Europe"
321
}
322
return regions.get(country.code, "Unknown")
323
324
class ExtendedQuery(graphene.ObjectType):
325
country = graphene.Field(ExtendedCountry, code=graphene.String())
326
327
def resolve_country(self, info, code):
328
country_obj = CountryObject(code=code)
329
return country_obj if country_obj.code else None
330
```
331
332
### Mutations
333
334
```python
335
import graphene
336
from django_countries.graphql.types import Country
337
from myapp.models import Person
338
339
class UpdatePersonCountry(graphene.Mutation):
340
"""Mutation to update person's country."""
341
342
class Arguments:
343
person_id = graphene.ID(required=True)
344
country_code = graphene.String(required=True)
345
346
person = graphene.Field(PersonType)
347
success = graphene.Boolean()
348
349
def mutate(self, info, person_id, country_code):
350
try:
351
person = Person.objects.get(id=person_id)
352
person.country = country_code
353
person.save()
354
return UpdatePersonCountry(person=person, success=True)
355
except Person.DoesNotExist:
356
return UpdatePersonCountry(person=None, success=False)
357
358
class Mutation(graphene.ObjectType):
359
update_person_country = UpdatePersonCountry.Field()
360
361
# Mutation example
362
"""
363
mutation UpdateCountry {
364
updatePersonCountry(personId: "1", countryCode: "CA") {
365
success
366
person {
367
name
368
country {
369
name
370
code
371
}
372
}
373
}
374
}
375
"""
376
```
377
378
### Subscriptions
379
380
```python
381
import graphene
382
from channels_graphql_ws import Subscription
383
from django_countries.graphql.types import Country
384
from myapp.models import Person
385
386
class CountryUpdates(Subscription):
387
"""Subscription for country-related updates."""
388
389
country_updated = graphene.Field(Country)
390
391
def subscribe(self, info, **kwargs):
392
"""Subscribe to country updates."""
393
return ["country_updates"]
394
395
def publish(self, info, **kwargs):
396
"""Publish country update."""
397
return CountryUpdates(country_updated=kwargs.get("country"))
398
399
class Subscription(graphene.ObjectType):
400
country_updates = CountryUpdates.Field()
401
```
402
403
### Error Handling
404
405
```python
406
import graphene
407
from django_countries.graphql.types import Country
408
from django_countries.fields import Country as CountryObject
409
410
class CountryError(graphene.ObjectType):
411
"""Error type for country operations."""
412
message = graphene.String()
413
code = graphene.String()
414
415
class CountryResult(graphene.Union):
416
"""Union type for country results."""
417
class Meta:
418
types = (Country, CountryError)
419
420
class SafeQuery(graphene.ObjectType):
421
country = graphene.Field(CountryResult, code=graphene.String())
422
423
def resolve_country(self, info, code):
424
"""Get country with error handling."""
425
try:
426
country_obj = CountryObject(code=code)
427
if country_obj.code:
428
return country_obj
429
else:
430
return CountryError(
431
message=f"Country with code '{code}' not found",
432
code="COUNTRY_NOT_FOUND"
433
)
434
except Exception as e:
435
return CountryError(
436
message=f"Error retrieving country: {str(e)}",
437
code="COUNTRY_ERROR"
438
)
439
```
440
441
### Performance Optimization
442
443
```python
444
import graphene
445
from django.utils.functional import cached_property
446
from django_countries.graphql.types import Country
447
from django_countries import countries
448
449
class OptimizedQuery(graphene.ObjectType):
450
"""Optimized country queries with caching."""
451
452
@cached_property
453
def _countries_cache(self):
454
"""Cache countries list for better performance."""
455
return {country.code: country for country in countries}
456
457
country = graphene.Field(Country, code=graphene.String())
458
countries = graphene.List(Country)
459
460
def resolve_country(self, info, code):
461
"""Optimized country lookup."""
462
country_tuple = self._countries_cache.get(code.upper())
463
if country_tuple:
464
return CountryObject(code=country_tuple.code)
465
return None
466
467
def resolve_countries(self, info):
468
"""Optimized countries list."""
469
# Use cached data to avoid repeated database/memory access
470
return [CountryObject(code=ct.code) for ct in self._countries_cache.values()]
471
```