graphql-python / graphene-django

Build powerful, efficient, and flexible GraphQL APIs with seamless Django integration.

Home Page:http://docs.graphene-python.org/projects/django/en/latest/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

many_to_many_extras use with through table referencing the same model on both foreign keys.

m4riok opened this issue · comments

commented

Hello,

I have been trying to use many_to_many_extras with a through model holding extra values on the relationship. I assume that in this use case the many_to_many_extras should reference the through model. Models are defined like so:

class Product(models.Model):
    class Meta:
        verbose_name = 'product'
        verbose_name_plural = 'products'

    def __str__(self):
        return self.name

    name = models.CharField(max_length=200)
    description = models.TextField(null=True, blank=True, default=None)
    is_derivative = models.BooleanField(default=False)
    company = models.ForeignKey(CBCompany, on_delete=models.CASCADE, related_name="products", null=True, blank=True, default=None)
    units = models.CharField(max_length=20, null=True, blank=True, default=None)
    imports = models.ManyToManyField(ProductImport, related_name="products", null=True, blank=True, default=None)
    sub_products = models.ManyToManyField('self',  through='ProductRelationship',through_fields=('derivative','component'), related_name='derives', symmetrical=False, null=True, blank=True, default=None)

class ProductRelationship(models.Model):
    derivative = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="components")
    component = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="derivatives")
    qty = models.IntegerField(null=True, blank=True, default=None)

And the create mutation like so:

class CreateProductMutation(DjangoCreateMutation):
    class Meta:
        model = Product
        login_required = True
        permissions = ("portal.add_product",)
        many_to_many_extras = {
            'components': {
                'exact': {'type': 'auto'},
                'remove': {'type': 'ID'}
            }
        }

When executing the following mutation:

mutation {
  createProduct( input: {name:"dasda", components: [ { component: 2 , qty: 50 } , {component: 3 , qty: 40}]}) {
    product {
      id
      name
      description
      isDerivative
      
    }
  }
}

I get hit with the following error:

{
  "errors": [
    {
      "message": "(1048, \"Column 'derivative_id' cannot be null\")",
      "locations": [
        {
          "line": 10,
          "column": 3
        }
      ],
      "path": [
        "createProduct"
      ]
    }
  ],
  "data": {
    "createProduct": null
  }
}

Am I wrong in assuming that derivative_id in the above use case should be automatically populated with the pk of the newly created product ? If so please point me in the right direction of achieving populating both the related sub_products and the qty value of the through model using many_to_many_extras.

I am assuming this is a bug since the input created CreateProductInputExactProductComponents has only:

   component: ID!
   qty: Int

Thank you for looking into this.