Skip to content
This repository has been archived by the owner on Jul 8, 2023. It is now read-only.

Update mutation fails with List #169

Open
dfunklove opened this issue Jan 27, 2023 · 4 comments
Open

Update mutation fails with List #169

dfunklove opened this issue Jan 27, 2023 · 4 comments

Comments

@dfunklove
Copy link

When I try to run an update mutation with a List, I get this error:

Cannot assign "'1'": "Rating.goal" must be a "Goal" instance."

Here is the mutation:

mutation {
  updateLesson(
    input: {id: "1", ratingSet: {set: [{goal: {id: "1"}, lesson: {id: "1"}, score: 10}]}}
  ) {
    ... on Lesson {
      id
    }
  }
}

And the relevant parts of my schema:

@gql.django.partial(models.Goal)
class GoalInputPartial(gql.NodeInputPartial):
    id: gql.ID

@gql.django.partial(models.Lesson)
class LessonInputPartial(gql.NodeInputPartial):
    id: gql.ID
    rating_set: Optional[gql.ListInput["RatingInput"]]

@gql.django.input(models.Rating)
class RatingInput:
    goal: GoalInputPartial
    lesson: LessonInputPartial
    score: auto

@gql.type
class Mutation:
    update_lesson: Lesson = login_required(gql.django.update_mutation(LessonInputPartial))

Am I doing something wrong or is this a bug?

@dfunklove dfunklove changed the title Unable to update with List Update mutation fails with List Jan 27, 2023
@bellini666
Copy link
Member

Since you are not using relay, you can't use NodeInput/NodeInputPartial. Both those types expects a GlobalID, and you are passing an ID

Try to remove the gql.NodeInputPartial subclass and it might fix it.

@dfunklove
Copy link
Author

dfunklove commented Jan 28, 2023

Thanks for the quick reply!
I tried the change you suggested and now I get this slightly different error:
Cannot assign "{'id': '1'}": "Rating.goal" must be a "Goal" instance.

I did some debugging and I think the issue might be in parse_input or _parse_data in strawberry_django_plus/mutations/resolvers.py. They seem to expect to find a ParsedObject or a OneToOneInput, OneToManyInput, etc. I can't find the place where the input string gets parsed into one of these types.

The mutation will run without errors if I change my input type to this:

@gql.django.input(models.Rating)
class RatingInput:
    goal_id: gql.ID
    lesson_id: gql.ID
    score: auto

Here is my model:

class Rating(models.Model):
    goal = models.ForeignKey(Goal, models.CASCADE)
    lesson = models.ForeignKey(Lesson, models.CASCADE)
    score = models.IntegerField()

However, if I try to create a Rating with this query:
createRating(input: {goalId: "2", lessonId: "1", score: 10})

I get this error:

{
  "data": {
    "createRating": {
      "messages": [
        {
          "kind": "VALIDATION",
          "field": "goal",
          "message": "This field cannot be null."
        },
        {
          "kind": "VALIDATION",
          "field": "lesson",
          "message": "This field cannot be null."
        }
      ]
    }
  }
}

So if the field is nested, I must use ID, but if it is at the root, then ID is not accepted. This inconsistency is very confusing!

@bellini666
Copy link
Member

I have to admit that I didn't fully test the input mutations with non relay types.

Can you provide a minimal reproduction example so that I can try to fix it?

@dfunklove
Copy link
Author

dfunklove commented Jan 28, 2023

Here you go!

demo_mutation_bug.zip

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants