djangodjango-modelsgraphqlmany-to-manygraphene-django

How can I properly interact with many-to-many relationship in Django+GraphQL?


How do I properly interact with many-to-many relationship in Django+GraphQL?

I have a Game model which has a many to many relationship to User model.

class Game(models.Model):
    name = models.CharField(max_length=256, blank=True)
    users = models.ManyToManyField(to=User, blank=True, related_name='games')


class User(AbstractUser):
    email = models.EmailField(max_length=128, verbose_name='email address', blank=False)

I need to connect it to GraphQL so I can read and modify that fields via mutations.

I already have a schema to work with Game without users but now I need to add users as well

{
  games {
    edges {
      node {
        id
        name
      }
    }
  }
}

But it doesn't work when I add users because the Game table in db doesn't have a users field. It has the games_game_users table that describes their relationship.

How can I modify my code to be able to work with game.users field?


Solution

  • If you want to interact with many-to-many relationship in Django+GraphQL you should define your Nodes correctly.

    That's how it should be defined for my case:

    class UserNode_(DjangoObjectType):
        class Meta:
            model = User
            interfaces = (graphene.relay.Node,)
    
    
    class GameNode(DjangoObjectType):
        class Meta:
            model = Game
            interfaces = (graphene.relay.Node,)
    
        users = graphene.List(UserNode_)
    
        def resolve_users(value_obj, info):
            return value_obj.users.all()
    

    So this GraphQL request will display your games and connected users

    {
      games {
        edges {
          node {
            id
            title
            users {
              id
              username
              email
            }
          }
        }
      }
    }
    

    To add or to remove users from the game use add() and remove() methods:

    game.users.add(new_user)
    game.users.remove(old_user)