How to avoid Graphene sorting an OrderedDict on query response? (Python, Django)

66 Views Asked by At

I am trying to return a dict of OrderedDicts from a Graphene endpoint in a Django application, by using the GenericScalar type field. The OrderedDicts are sorted based on value, but the API seems to re-sort the dicts by key.

The OrderedDicts items format is: { id : [name, amount] }

Example of one of the OrderedDicts that I send:

{ 'foods': {
    3: ['apple', 5],
    1: ['banana', 7],
    2: ['carrot', 3]
  }, 
  'animals': {
    5: ['cat', 3],
    3: ['dog', 10],
    1: ['pig', 5],
  }
}

What is received in the endpoint response:

{ 'foods': {
    1: ['banana', 7],
    2: ['carrot', 3],
    3: ['apple', 5],
  }, 
  'animals': {
    1: ['pig', 5],
    3: ['dog', 10],
    5: ['cat', 3],
  }
}

I am specifically using OrderedDicts because the order is important, but I have not found a way of avoiding Graphene to re-sort the OrderedDicts by key.

This is the how the ObjectType and Query are declared, althought is is nothing out of the ordinary.

class DashboardType(g.ObjectType):
    data = GenericScalar()

class Query(object):
    dashboard = Field(DashboardDataType, id=ID(), date=Date())
   
    def resolve_dashboard(self, info, **kwargs):
        data = function_to_get_the_data(kwargs)
        # up until this point the data is still sorted correctly
        return data

The data is sorted as expected up until the response is sent by the Graphene API. I would expect the order to be mantained, but it is not.

Any suggestions on how to achieve this? I didn't think it would be so difficult, but I am out of ideas.

1

There are 1 best solutions below

2
Michel Floyd On BEST ANSWER

I would suggest as a model:

type Thing {
  id: ID!
  name: String!
  subthings: [Subthing]
}

type Subthing {
  id: ID!
  name: String!
  amount: Int
}

Then you could have a guery:

query getThings(orderBy: String, direction: String): [Thing]

And against that you could execute:

query getThingsOrderByName($orderBy: 'name', $direction: 'asc') {
  query getThings(orderBy: $orderBy, direction: $direction) {
    id
    name
    subthings {
      id
      name
      amount
    }
  }
}

Your subThings resolver could then sort the subThings based on the orderBy and 'direction' query parameters.

Your return object would then look like:

[
  {
    "id": `
    "name": "foods"
    "subthings": [
      {
        "id": 3,
        "name": "apple",
        "amount": 5,
      },
      etc…
    ]
  }
]