在Django中使用Graphql:使用所有对象的相关名称反转外键关系

xuo3flqw  于 2023-01-03  发布在  Go
关注(0)|答案(1)|浏览(114)

bounty将在6天后过期。回答此问题可获得+100声望奖励。Sachin Rajput希望引起更多人对此问题的关注:我想知道我是如何使用graphql(django)使用related_name或其他方式执行反向外键查询的

我正在使用graphene-django,graphql和django,我想使用drf的反向外键概念使用相关的名称,但目前我面临着实现的困难,我已经提出了模型,代码和下面的输出截图

import asyncio

asyncio.set_event_loop(asyncio.new_event_loop())
import graphene
from graphene_django import DjangoObjectType
from .models import Category, Book, Grocery, FileUpload
from django.db.models import Q
from graphene_file_upload.scalars import Upload
import decimal

class BookType(DjangoObjectType):
    class Meta:
        model = Book
        fields = (
            'id',
            'title',
            'author',
            'isbn',
            'pages',
            'price',
            'quantity',
            'description',
            'status',
            'date_created',
        )

class FileUploadType(DjangoObjectType):
    class Meta:
        model = FileUpload
        fields = ('id', 'file')

class GroceryType(DjangoObjectType):
    class Meta:
        model = Grocery
        # fields = (
        #     'product_tag',
        #     'name',
        #     'category',
        #     'price',
        #     'quantity',
        #     'imageurl',
        #     'status',
        #     'date_created',
        # )

class CategoryType(DjangoObjectType):
    grocery = graphene.List(GroceryType)

    class Meta:
        model = Category
        fields = ('id', 'title', 'grocery')

class Query(graphene.ObjectType):
    books = graphene.List(
        BookType,
        search=graphene.String(),
        first=graphene.Int(),
        skip=graphene.Int(),
    )
    categories = graphene.List(CategoryType)
    # books = graphene.List(BookType)
    groceries = graphene.List(GroceryType)
    files = graphene.List(FileUploadType)

    # def resolve_books(root, info, **kwargs):
    #     # Querying a list
    #     return Book.objects.all()
    def resolve_books(self, info, search=None, first=None, skip=None, **kwargs):
        qs = Book.objects.all()

        if search:
            filter = (
                    Q(id=search) |
                    Q(title__icontains=search)
            )
            qs = qs.filter(filter)

        if skip:
            qs = qs[skip:]

        if first:
            qs = qs[:first]

        return qs

    def resolve_categories(root, info, **kwargs):
        # Querying a list
        r = []
        for ele in Category.objects.all().prefetch_related("grocery"):
            r.append(ele.grocery.all())
        return Category.objects.all().prefetch_related("grocery")

    def resolve_groceries(root, info, **kwargs):
        # Querying a list
        print("help")
        qs = Grocery.objects.all()
        print(qs)
        return qs

    def resolve_files(root, info, **kwargs):
        # Querying a list
        return FileUpload.objects.all()

class UpdateCategory(graphene.Mutation):
    class Arguments:
        # Mutation to update a category
        title = graphene.String(required=True)
        id = graphene.ID()

    category = graphene.Field(CategoryType)

    @classmethod
    def mutate(cls, root, info, title, id):
        category = Category.objects.get(pk=id)
        category.title = title
        category.save()

        return UpdateCategory(category=category)

class CreateCategory(graphene.Mutation):
    class Arguments:
        # Mutation to create a category
        title = graphene.String(required=True)

    # Class attributes define the response of the mutation
    category = graphene.Field(CategoryType)

    @classmethod
    def mutate(cls, root, info, title):
        category = Category()
        category.title = title
        category.save()

        return CreateCategory(category=category)

class FileUploadMutation(graphene.Mutation):
    class Arguments:
        file = Upload(required=True)

    success = graphene.Boolean()

    def mutate(self, info, file, **kwargs):
        # do something with your file
        file_obj = FileUpload()
        file_obj.file = file
        file_obj.save()
        return FileUploadMutation(success=True)

class BookInput(graphene.InputObjectType):
    title = graphene.String()
    author = graphene.String()
    pages = graphene.Int()
    price = graphene.Int()
    quantity = graphene.Int()
    description = graphene.String()
    status = graphene.String()

class GroceryInput(graphene.InputObjectType):
    product_tag = graphene.String()
    name = graphene.String()
    category_id = graphene.String(required=True)

    price = graphene.Int()
    quantity = graphene.Int()
    imageurl = graphene.String()
    status = graphene.String()

class CreateBook(graphene.Mutation):
    class Arguments:
        input = BookInput(required=True)

    book = graphene.Field(BookType)

    @classmethod
    def mutate(cls, root, info, input):
        book = Book()
        book.title = input.title
        book.author = input.author
        book.pages = input.pages
        book.price = input.price
        book.quantity = input.quantity
        book.description = input.description
        book.status = input.status
        book.save()
        return CreateBook(book=book)

class UpdateBook(graphene.Mutation):
    class Arguments:
        input = BookInput(required=True)
        id = graphene.ID()

    book = graphene.Field(BookType)

    @classmethod
    def mutate(cls, root, info, input, id):
        book = Book.objects.get(pk=id)
        book.name = input.name
        book.description = input.description
        book.price = decimal.Decimal(input.price)
        book.quantity = input.quantity
        book.save()
        return UpdateBook(book=book)

class CreateGrocery(graphene.Mutation):
    class Arguments:
        input = GroceryInput(required=True)

    grocery = graphene.Field(GroceryType)
    category = graphene.Field(CategoryType)

    @classmethod
    def mutate(cls, root, info, input):
        if input is None:
            return CreateGrocery(grocery=None)
        grocery = Grocery.objects.create(**input)
        return CreateGrocery(grocery=grocery)

class Mutation(graphene.ObjectType):
    update_category = UpdateCategory.Field()
    create_category = CreateCategory.Field()
    create_book = CreateBook.Field()
    update_book = UpdateBook.Field()
    create_grocery = CreateGrocery.Field()
    # file_upload = FileUpload.Field()

schema = graphene.Schema(query=Query, mutation=Mutation)

我创建的模型如下

from django.db import models

# Create your models here.
class Category(models.Model):
    title = models.CharField(max_length=255)

    class Meta:
        verbose_name_plural = 'Categories'
    def __str__(self):
        return self.title

class Book(models.Model):
    title = models.CharField(max_length=150)
    author = models.CharField(max_length=100, default='John Doe')
    isbn = models.CharField(max_length=13)
    pages = models.IntegerField()
    price = models.IntegerField()
    quantity = models.IntegerField()
    description = models.TextField()
    status = models.BooleanField()
    date_created = models.DateField(auto_now_add=True)

    class Meta:
        ordering = ['-date_created']

    def __str__(self):
        return self.title

class Grocery(models.Model):
    product_tag = models.CharField(max_length=10)
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, related_name='grocery', on_delete=models.CASCADE)
    price = models.IntegerField()
    quantity = models.IntegerField()
    imageurl = models.URLField()
    status = models.BooleanField()
    date_created = models.DateField(auto_now_add=True)

    class Meta:
        ordering = ['-date_created']

    def __str__(self):
        return self.name

class FileUpload(models.Model):
    file = models.FileField()

现在我想为每个类别,我应该能够列出杂货以及如下所示

{
  "data": {
    "categories": [
      {
        "id": "1",
        "title": "Plastic"
        "grocery" :{
            #grocery related fields
         }
      },
      
    ]
  }
}

目前,当我尝试我得到以下错误x1c 0d1x
我当前正在使用的请求

query listCategories{
  categories {
      id
        title
        grocery {
        name
      }
    }
}

我得到的错误响应

{
  "errors": [
    {
      "message": "Expected Iterable, but did not find one for field 'CategoryType.grocery'.",
      "locations": [
        {
          "line": 56,
          "column": 7
        }
      ],
      "path": [
        "categories",
        0,
        "grocery"
      ]
    },
    {
      "message": "Expected Iterable, but did not find one for field 'CategoryType.grocery'.",
      "locations": [
        {
          "line": 56,
          "column": 7
        }
      ],
      "path": [
        "categories",
        1,
        "grocery"
      ]
    },
    {
      "message": "Expected Iterable, but did not find one for field 'CategoryType.grocery'.",
      "locations": [
        {
          "line": 56,
          "column": 7
        }
      ],
      "path": [
        "categories",
        2,
        "grocery"
      ]
    },
    {
      "message": "Expected Iterable, but did not find one for field 'CategoryType.grocery'.",
      "locations": [
        {
          "line": 56,
          "column": 7
        }
      ],
      "path": [
        "categories",
        3,
        "grocery"
      ]
    }
  ],
  "data": {
    "categories": [
      {
        "id": "1",
        "title": "Plastic",
        "grocery": null
      },
      {
        "id": "2",
        "title": "Plastic",
        "grocery": null
      },
      {
        "id": "3",
        "title": "Plastic",
        "grocery": null
      },
      {
        "id": "4",
        "title": "Plastic",
        "grocery": null
      }
    ]
  }
}
5lhxktic

5lhxktic1#

使用graphene_django.DjangoListField

from graphene_django import DjangoListField, DjangoObjectType

class CategoryType(DjangoObjectType):
    grocery = DjangoListField(GroceryType)

或者,实现冲突解决程序:

import graphene
from graphene_django import DjangoObjectType

class CategoryType(DjangoObjectType):
    grocery = graphene.List(GroceryType)

    @staticmethod
    def resolve_grocery(parent, info):
        return parent.grocery.all()

相关问题