This question is more about what's the best practice than how to monkey-patch Graphene to accomplish what I want.
Django Graphene turns model's choices automagically in enums.
Lets say I have this model:
class Car(models.Model):
brand = models.PositiveSmallIntegerField(
choices=(
(1, "Audi"),
(2, "Mercedes Benz"),
(3, "BMW")
)
)
with this node:
class CarNode(DjangoObjectType):
class Meta:
model = Car
filter_fields = []
interfaces = (relay.Node,)
then, running the following query:
query Cars {
cars {
edges {
node {
id
brand
}
}
}
}
results in this response:
{
"data": {
"cars": {
"edges": [
{
"node": {
"id": "Q2FyTm9kZTox",
"brand": "A_1"
}
},
{
"node": {
"id": "Q2FyTm9kZToy",
"brand": "A_2"
}
},
{
"node": {
"id": "Q2FyTm9kZToz",
"brand": "A_3"
}
}
]
}
}
}
At this point I may want to make a custom enum to turn A_1, A_2 and A_3 into capitalized, snake cased values, to make them self-descriptive...
class CarBrand(graphene.Enum):
AUDI = 1
MERCEDES_BENZ = 2
BMW = 3
@property
def description(self):
if self == CarBrand.AUDI:
return 'Audi'
if self == CarBrand.MERCEDES_BENZ:
return 'Mercedes Benz'
if self == CarBrand.BMW:
return 'BMW'
return 'Other brand'
class CarNode(DjangoObjectType):
brand = CarBrand()
...
Now, the response looks A LOT better:
{
"data": {
"cars": {
"edges": [
{
"node": {
"id": "Q2FyTm9kZTox",
"brand": "AUDI"
}
},
{
"node": {
"id": "Q2FyTm9kZToy",
"brand": "MERCEDES_BENZ"
}
},
{
"node": {
"id": "Q2FyTm9kZToz",
"brand": "BMW"
}
}
]
}
}
}
Well, that's what I've done in a real life application I'm currently working on.
The problem is there are 11 fields like the "brand" one in my example above and some of them have hundreds of choices.
One of the clients consuming my API is requesting the values coming in the description right in the main query, they pretend something like:
{
"data": {
"cars": {
"edges": [
{
"node": {
"id": "Q2FyTm9kZTox",
"brand": "Audi"
}
},
{
"node": {
"id": "Q2FyTm9kZToy",
"brand": "Mercedes Benz"
}
},
{
"node": {
"id": "Q2FyTm9kZToz",
"brand": "BMW"
}
}
]
}
}
}
There's a way to query an enum to get an object containing both the name and the description per choice, which is really good because an implementor could just make some kind of function to accomplish that.
query introspectTaskStateEnumType {
__type(name: "CarBrand") {
enumValues {
name
description
}
}
}
and you get
{
"data": {
"__type": {
"enumValues": [
{
"name": "AUDI",
"description": "Audi"
},
{
"name": "MERCEDES_BENZ",
"description": "Mercedes Benz"
},
{
"name": "BMW",
"description": "BMW"
}
]
}
}
}
Now, the final questions are:
- What's the best practice here?
- What's the right solution I should give to my client?
- Why there's no way to retrieve the ENUM description right in the query?
I expect to build up a discussion regarding best practices more than seeing possible ways to retrieve the description with code, because I know there could be many ways to make it works that way.