I am new to Django/Graphql/Graphene and struggling to write a nested mutation with several foreign keys and a many-to-many relation. I have read several posts on this topic but still struggling.
I have highlighted several questions within the below code. It would be great to help me both on the foreign keys (Fare
, Year
) and on the Many-to-Many field (Parent
), which I have not even included yet in the graphical request. It would be good to have help both on how to write the Python graphene code and then the Graphiql request. Many thanks to all
Here is the code:
Model (extract):
class Student(models.Model):
first = models.CharField(max_length=64)
last = models.CharField(max_length=64)
email = models.EmailField()
phone = models.CharField(max_length=64)
year = models.ForeignKey(Year, on_delete=models.CASCADE, related_name="students", blank=True)
fare = models.ForeignKey(Fare, on_delete=models.CASCADE, related_name="at_fare", blank=True)
parents = models.ManyToManyField(Parent, related_name="children", blank=True)
Schema.py:
class StudentType(DjangoObjectType):
class Meta:
model = Student
// is the Student Type necessary????
class FareType(DjangoObjectType):
class Meta:
model = Fare
class YearType(DjangoObjectType):
class Meta:
model = Year
class ParentType(DjangoObjectType):
class Meta:
model = Parent
Input object types:
class StudentInput(graphene.InputObjectType):
#id = graphene.ID() // is this field necessary??
first = graphene.String()
last = graphene.String()
email = graphene.String()
phone = graphene.String()
year = graphene.Field(YearInput)
fare = graphene.Field(FareInput)
parents = graphene.List(ParentInput)
class FareInput(graphene.InputObjectType):
#id = graphene.ID()
level = graphene.String()
price = graphene.Int()
currency = graphene.String()
class YearInput(graphene.InputObjectType):
#id = graphene.ID()
name = graphene.String()
class ParentInput(graphene.InputObjectType):
id = graphene.ID()
first = graphene.String()
last = graphene.String()
email = graphene.String()
phone = graphene.String()
is_primary_contact = graphene.Boolean()
is_billing_contact = graphene.Boolean()
address_line1 = graphene.String()
address_line2 = graphene.String()
postcode = graphene.String()
city = graphene.String()
country = graphene.String()
Mutation (I haven't even managed to include the Parents field so far):
class CreateStudent(graphene.Mutation):
ok = graphene.Boolean()
student = graphene.Field(StudentType)
class Arguments:
student_data=StudentInput(required=True)
year_data=YearInput(required=True)
fare_data=FareInput(required=True)
def mutate(self, info, student_data, year_data, fare_data):
student_data.year = year_data
student_data.fare = fare_data
student = Student.objects.create(**student_data)
return CreateStudent(ok=ok, student=student)
GraphIQL mutation:
mutation CreateStudent($studentData: StudentInput!, $yearData: YearInput!, $fareData: FareInput!) {
createStudent(studentData: $studentData, yearData: $yearData, fareData: $fareData) {
student {
id
first
last
phone
email
year {
id
name
}
fare {
id
level
price
currency
}
}
}
}
Variables
{ "studentData":
{
"first":"Jake",
"last":"Blog",
"phone":"+447917421894",
"email":"[email protected]"
},
"yearData": {
"name": "Test"
},
"fareData": {"level": "MatTest", "price": 160, "currency": "EUR"}
}
Here is the error message from Graphiql, but I suspect there could be other issues.
{
"errors": [
{
"message": "null value in column \"fare_id\" of relation \"tutor_student\" violates not-null constraint\nDETAIL: Failing row contains (13, Jake, Blog, [email protected], +447817421894, null, null).\n",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"createStudent"
]
}
],
"data": {
"createStudent": null
}
}