question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

returned pk ids are string by default - how to serialize pks as int

See original GitHub issue

I was surprised to discover that by default, all DjangoObjectType schema nodes had primary key ids that were strings:

class UserType(DjangoObjectType):
    id = graphene.Int(source='pk')
    is_current_user = graphene.Boolean()

    class Meta:
        model = User

    def resolve_is_current_user(self, info):
        current_user = info.context.get('current_user')
        if current_user:
            return self.id is current_user.id
        return False

class UsersQuery(graphene.ObjectType):
    users = graphene.List(UserType)
    def resolve_users(self, info, **kwargs):
        return User.objects.all()

schema = graphene.Schema(query=ChatQuery)

gql_to_execute = """
query {
  users {
    id
    username
    isCurrentUser
  }
}
"""

current_user = User.objects.get(id=1)
result = schema.execute(gql_to_execute, context_value={"current_user": current_user}

print(json.dumps(result.data, indent=4))
printed = {
    "users": [
        {
            "id": "3",
            "name": "User Three",
            "username": "user3",
            "isCurrentUser": false,
            "photoUrl": ""
        },
        {
            "id": "2",
            "name": "User Two",
            "username": "user2",
            "isCurrentUser": false,
            "photoUrl": ""
        },
        {
            "id": "1",
            "name": "User One",
            "username": "user1",
            "isCurrentUser": true,
            "photoUrl": ""
        }
    ]
}

After seeing test_should_auto_convert_id asserted that AutoField instances were converted to graphene.ID types, I looked up the graphene type definition and noticed that the serializer for graphene.ID is str. This might make sense for graphene, but I don’t think it makes sense for django-graphene, where most users will have integer primary keys from relational databases.

I was able to coerce the id to an int by explicitly marking the field type as an int:

class UserType(DjangoObjectType):
    id = graphene.Int(source='pk')
    is_current_user = graphene.Boolean()

I ended up subclassing DjangoObjectType to make this customization for all of my Django Model nodes, but this won’t help other users who wish to keep their primary key type intact.

Would django-graphene be open to a PR adding this directly to DjangoObjectType?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:8
  • Comments:9 (3 by maintainers)

github_iconTop GitHub Comments

16reactions
dperetticommented, May 25, 2018

I beg to differ. It’s an int in Django, therefore I expect the frontend to get an int as well. Period. What I don’t expect: the fact that graphene-django assumes that my frontend state is managed with string ids (it is not).

9reactions
jkimbocommented, May 26, 2018

@dperetti @codekiln in GraphQL all ID types are represented as strings: https://graphql.org/learn/schema/#scalar-types

ID: The ID scalar type represents a unique identifier, often used to refetch an object or as the key for a cache. The ID type is serialized in the same way as a String; however, defining it as an ID signifies that it is not intended to be human‐readable.

graphene-django has made the decision that Django ID’s should be mapped to the GraphQL concept of ID’s and I think that is the right decision. You can always work around it like @codekiln has by explicitly mapping the Django field to a graphene Int field:

class UserType(DjangoObjectType):
    id = graphene.Int(source='pk')
Read more comments on GitHub >

github_iconTop Results From Across the Web

Using a UUID as a primary key in Django models (generic ...
Point the ForeignKey to the UUID (using to_field='id' ) to allow your foreign-keys to properly represent the Pseudo-PK instead of the numeric ID ......
Read more >
Serializing Django objects
The primary key is always serialized as the pk element in the resulting output; ... as serialize , a string or stream of...
Read more >
Using @JsonIdentityReference to always serialize a POJO by id
@JsonIdentityReference annotation can be used along with @JsonIdentityInfo to serialize Object by its id instead of as full POJO.
Read more >
Be Careful with UUID or GUID as Primary Keys - Hacker News
I can't speak for other databases, but SQL Server's NEWSEQUENTIALID is only guaranteed until the server reboots. At which point the next UUID ......
Read more >
Populating ID columns via Sequence - Ask TOM
Quasi SQL from: on insert for each row trigger... ... from dual; c)OR some other approach... maybe a default like (sysdate for dates)?...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found