Search code examples
djangographqldjango-oscargraphene-python

How to reorder Django-Graphene sub-query?


I am trying to reorder my ProductLandingPageImageNode according to a 'order' field on my ProductLandingpageImage Model.

If this would be a direct query I could write a resolve method, but I cannot find out how this is possible on a sub-query.

MAIN QUERY:

class Query(graphene.ObjectType):
  class Meta:
    interfaces = [relay.Node, ]

  product_oscar = graphene.List(ProductNode)
  productByID = DjangoFilterConnectionField(ProductNode)


  def resolve_product_oscar(self, info, **kwargs):
    return Product.objects.all()

PRODUCTNODE:

class ProductNode(DjangoObjectType):
  class Meta:
    model = Product
    interfaces = (relay.Node, )
    filter_fields = {
      "slug" : ['iexact']
    }

PRODUCTLANDINGPAGEIMAGENODE:

class ProductLandingpageImageNode(DjangoObjectType):
  class Meta:
    model = ProductLandingpageImage
    interfaces = (relay.Node, )

How to solve this?


LANDINGPAGEIMAGE MODEL on request:

class AbstractProductLandingpageImage(models.Model):
  """
    A landingpageimage of a product
  """
  product = models.ForeignKey(
    'catalogue.Product',
    on_delete=models.CASCADE,
    related_name='landingpage_image',
    verbose_name=_("Product landingpage"))
  date_created = models.DateTimeField(_("Date created"), auto_now_add=True)
  original = models.ImageField(
    _("Landingpage original"), upload_to=settings.OSCAR_IMAGE_FOLDER, max_length=255, blank=True)

  ORDER_CHOICES = (
    (1, 1),
    (2, 2),
    (3, 3),
    (4, 4),
    (5, 5),
    (6, 6),
  )

  order = models.PositiveIntegerField(default=1, choices=ORDER_CHOICES, blank=True)

class Meta:
    abstract = True
    app_label = 'catalogue'
    # Any custom models should ensure that this ordering is unchanged, or
    # your query count will explode. See AbstractProduct.primary_image.
    ordering = ["order"]
    verbose_name = _('Product landingpage image')
    verbose_name_plural = _('Product landingpage images')

The default ordering in the Meta does somehow not work. What is also strange when I Graphql query for the order value is not not return "1, 2, 3..." but "A_1, A_2..."


Solution

  • Maybe something like this. Since you don't list your Product model, I just made up the name of the field on Product that references the image, so you should rename that. If there's a many-to-one relationship relationship between product and image maybe you want a different field name.

    import graphene
    from graphene.django.types import DjangoObjectType
    
    class ProductNode(DjangoObjectType):
        name_of_your_image_field = graphene.Field(ProductLandingpageImageNode)
    
        class Meta:
            model = Product
            ... other Meta data
    
    
        def resolve_name_of_your_image_field(self, info):  # rename to match field
            # Put the code that returns a single ProductLandingpageImage instance here
            # graphene-django will convert your ProductLandingPageImage instance into a ProductLandingpageImageNode
    

    This is for returning a single ProductLandingPageIMage . If you want to return multiple instances, then change the field definition to a list

        name_of_your_image_field = graphene.List(ProductLandingpageImageNode)
    

    and then in your resolver return multiple ProductLandingPageImage instances -- for example a queryset that is sorted the way that you want it.