From 6354ed892b57886c51e4a032e375cc77d182e68c Mon Sep 17 00:00:00 2001 From: plebbimon Date: Mon, 17 Jul 2023 22:59:35 +0200 Subject: [PATCH 1/2] chore(docs): added example for m2m `through` fields --- docs/guide/nested-fields.rst | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/docs/guide/nested-fields.rst b/docs/guide/nested-fields.rst index 4b0b7df..a469fbf 100644 --- a/docs/guide/nested-fields.rst +++ b/docs/guide/nested-fields.rst @@ -283,6 +283,61 @@ populator of the relationship. If you don't have an existing type for creating a user, e.g. the "CreateCatInput" we used above, you can set the type to "auto", which will create a new type. +Many to many with `through` models +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Using `graphene-django-cud`, a `through` model is more akin to a many to one relationship, as it is +an intermediate model that connects two other models with itself. + +If you have a many to many relationship with a `through` model, you can use +a `many_to_one_extras` field to specify how to handle the `through` model. +There's also usually no need to specify the `many_to_many_extras` field, as +the `through` model will be used instead. + +Suppose we have a `Dog` model with a many to many relationship +with a `Cat` model, but we want to keep track of the number of times a dog +has fought a cat. We can do this with a `through` model: + +.. code:: python + + class Dog(models.Model): + owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL) + name = models.TextField() + fights = models.ManyToManyField(Cat, through='Fight') + + class Fight(models.Model): + dog = models.ForeignKey(Dog, on_delete=models.CASCADE, related_name='fights') + cat = models.ForeignKey(Cat, on_delete=models.CASCADE, related_name='fights') + times = models.IntegerField(default=0) + +We can then create a mutation to create a dog, and add a fight to it: + +.. code:: python + + class CreateDogMutation(DjangoCreateMutation): + class Meta: + model = Dog + many_to_one_extras = { + 'fights': { + 'exact': {"type": "auto"} + } + } + +This will infer the dog's ID, and allows us to create a fight in the same +mutation: + +.. code:: + + mutation { + createDog(input: { + name: "Buster", + fights: [{cat: "Q2F0Tm9kZTox", times: 1}] + }}){ + dog{ + ...DogInfo + } + } + } + One to one extras ~~~~~~~~~~~~~~~~~ From 9e07fd090813135020ab322fa52238aa2be828b2 Mon Sep 17 00:00:00 2001 From: Plebbimon Date: Mon, 15 Jan 2024 18:22:16 +0100 Subject: [PATCH 2/2] chore(feedback): minor edits to explain `through` in Django --- docs/guide/nested-fields.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/guide/nested-fields.rst b/docs/guide/nested-fields.rst index a469fbf..364a3ed 100644 --- a/docs/guide/nested-fields.rst +++ b/docs/guide/nested-fields.rst @@ -285,13 +285,14 @@ you can set the type to "auto", which will create a new type. Many to many with `through` models ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Using `graphene-django-cud`, a `through` model is more akin to a many to one relationship, as it is -an intermediate model that connects two other models with itself. +The way Django handles a `through` model internally is functionally similar to using many to one relationships. This +implies that the more convienient option is to use `many_to_one_extras` instead of `many_to_many_extras` when dealing +with `through` models. If you have a many to many relationship with a `through` model, you can use a `many_to_one_extras` field to specify how to handle the `through` model. -There's also usually no need to specify the `many_to_many_extras` field, as -the `through` model will be used instead. +Due to how the m2m fields are automatically generated using the input schema, it is recommended to use the +`many_to_one_extras` field instead of the `many_to_many_extras` field. Suppose we have a `Dog` model with a many to many relationship with a `Cat` model, but we want to keep track of the number of times a dog