Django GraphQL不会使用外键创建新数据

f3temu5u  于 2023-03-20  发布在  Go
关注(0)|答案(1)|浏览(92)

我是Graphene、Django和GraphQL的新手,我正在尝试理解在更新使用外键的表时它是如何工作的。我能够成功地创建一个新作者,这需要填充外键字段,但我不能创建一本新书,这需要填充外键字段。

**我的问题:**我的实现中有什么问题阻止我创建新书?

正在发生什么

当我运行CreateNewBook突变时(如下所示),GraphQL返回null作为标题,并且没有数据添加到dim_all_books

我的期待

我希望当我运行CreateNewBook变异时,返回结果显示书名,并向表dim_all_books追加一条新记录。

我尝试过的

当我运行下面的查询时,它工作正常。

mutation CreateNewAuthor{
  createAuthor(authorData: {
    authorName: "William Shakespeare",
    yearBorn: "1722",
    yearDied: "1844",
    country: "Austria",
    booksWritten: 11
  }) {
    author {
      authorName
    }
  }
}

但是,当我在该查询之后立即运行以下查询时,得到以下结果:
x一个一个一个一个x一个一个二个x
无论我为authorName输入什么值,都会出现这种结果。

实施

项目创建
django-admin startproject core
python3 manage.py startapp books
python3 manage.py startapp authors
书籍
# books/models.py
class Book(models.Model):
    title = models.CharField(max_length=100)
    subtitle = models.CharField(max_length=100)
    author_name = models.ForeignKey(
        'authors.author',
        related_name='authors',
        verbose_name='author_name',
        db_column='author_name',
        blank=True,
        null=True,
        on_delete=models.SET_NULL
    )
    year_published = models.CharField(max_length=10)
    review = models.FloatField()

    class Meta:
        db_table = "dim_all_books"
    
    def __str__(self):
        return self.title
# books/schema.py
class BookType(DjangoObjectType):
    class Meta:
        model = Book
        fields = '__all__'

class BookInputType(graphene.InputObjectType):
    title = graphene.String()
    subtitle = graphene.String()
    author_name = graphene.String()
    year_published = graphene.String()
    review = graphene.Float()

...

class CreateBook(graphene.Mutation):
    class Arguments:
        book_data = BookInputType(required=True)

    book = graphene.Field(BookType)

    @staticmethod
    def mutate(root, info, book_data=None):
        book_instance = Book(
            title=book_data.title,
            subtitle=book_data.subtitle,
            author_name=book_data.author_name,
            year_published=book_data.year_published,
            review=book_data.review
        )
        book_instance.save()
        return CreateBook(book=book_instance)

...

class Mutation(graphene.ObjectType):
    create_book = CreateBook.Field()
    update_book = UpdateBook.Field()
    delete_book = DeleteBook.Field()
作者
# authors/models.py
class Author(models.Model):
    author_name = models.CharField(
        max_length=100, 
        primary_key=True, 
        db_column='author_name',
        default='Unknown'
    )
    year_born = models.CharField(max_length=10)
    year_died = models.CharField(max_length=10, blank=True, null=True)
    country = models.CharField(max_length=60)
    books_written = models.PositiveSmallIntegerField()

    class Meta:
        db_table = 'dim_all_authors'
    
    def __str__(self):
        return self.name
# authors/schema.py
class AuthorType(DjangoObjectType):
    class Meta:
        model = Author
        fields = '__all__'

class AuthorInputType(graphene.InputObjectType):
    author_name = graphene.String()
    year_born = graphene.String()
    year_died = graphene.String()
    country = graphene.String()
    books_written = graphene.Int()

...

class CreateAuthor(graphene.Mutation):
    class Arguments:
        author_data = AuthorInputType(required=True)
    
    author = graphene.Field(AuthorType)

    @staticmethod
    def mutate(root, info, author_data=None):
        author_instance = Author(
            author_name = author_data.author_name,
            year_born = author_data.year_born,
            year_died = author_data.year_died,
            country = author_data.country,
            books_written = author_data.books_written
        )
        author_instance.save()
        
        return CreateAuthor(author=author_instance)

...

class Mutation(graphene.ObjectType):
        create_author = CreateAuthor.Field()
        update_author = UpdateAuthor.Field()
        delete_author = DeleteAuthor.Field()

然后在core/schema.pycore.settings.py中设置这些模式,如下所示:

# core/schema.py
import graphene
from authors.schema import Query as AuthorQuery
from authors.schema import Mutation as AuthorMutation
from books.schema import Query as BookQuery
from books.schema import Mutation as BookMutation

class Query(BookQuery, AuthorQuery):
    pass

class Mutation(BookMutation, AuthorMutation):
    pass

schema = graphene.Schema(query=Query, mutation=Mutation)
# core/settings.py

...

GRAPHENE = {
    "SCHEMA": "core.schema.schema"
}
lmvvr0a8

lmvvr0a81#

为了达到这个目的,你必须传入你希望外键指向的对象的示例。在这个例子中,我希望[dim_all_books].author_name指向[dim_all_authors].author_name。所以,你不能只传入“William Shakespear”,而是需要传入Author.objects.get(pk=book_data.author_name)的结果。这需要修改我的books/schema.py文件,如下所示。
1.为外键引用的模型添加一个导入,在我的例子中,这意味着在文件的顶部添加from authors.models import Author
1.我不得不用下面的代码更新我的变异逻辑。

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

    book = graphene.Field(BookType)

    @staticmethod
    def mutate(root, info, book_data=None):
        author = Author.objects.get(pk=book_data.author_name)
        book_instance = Book(
            title=book_data.title,
            subtitle=book_data.subtitle,
            author_name=author,
            year_published=book_data.year_published,
            review=book_data.review
        )
        book_instance.save()
        return CreateBook(book=book_instance)

相关问题