JavaRush /Курсы /Модуль 3: Django /Работа с Django моделями через GraphQL

Работа с Django моделями через GraphQL

Модуль 3: Django
24 уровень , 5 лекция
Открыта

Что ж, теперь пора сделать следующий шаг — связать наши Django-модели (то есть базу данных) с миром GraphQL. Представьте, что API — это некий официант в ресторане, который доставляет данные к вашему столу. А Django модели — это шеф-повара на кухне. Сегодня вы научитесь "передавать заказы" между ними.

Предварительные знания

Пару слов для настройки контекста. Мы предполагаем, что вы уже:

  1. Понимаете, что такое GraphQL: запросы, мутации и др.
  2. Успешно установили Graphene-Django и настроили базовый GraphQL API.
  3. Имеете Django проект с подключённой базой данных и хотя бы одной рабочей моделью.

План на сегодня

Вот что мы сегодня изучим и опробуем:

  1. Как связать Django модели с GraphQL.
  2. Использование DjangoObjectType для работы с моделями.
  3. Получение данных из базы через GraphQL.
  4. Пример создания простого запроса, работающего с моделью.
  5. Обсуждение типичных ошибок и подводных камней.

Интеграция моделей Django с GraphQL

Одним из ключевых инструментов, которые делает Graphene-Django таким удобным, является класс DjangoObjectType. Этот класс выступает "мостом" между вашими Django моделями и GraphQL-типами. Важно понимать, что он автоматически создаёт типы на основе ваших моделей, что избавляет вас от необходимости делать это вручную.

Как это работает? На высоком уровне DjangoObjectType:

  • Сканирует поля указанной модели.
  • Преобразует эти поля в соответствующие GraphQL-типы.
  • Добавляет в схему всё, что нужно для работы с данной моделью через API.

Использование DjangoObjectType для связки моделей и типов GraphQL

Давайте начнём с простой Django-модели Book. Мы предполагаем, что вы работаете над системой управления книгами (почему бы и нет, книги — это классика!).

# models.py
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.CharField(max_length=100)
    published_date = models.DateField()
    price = models.DecimalField(max_digits=6, decimal_places=2)

    def __str__(self):
        return self.title

Эта модель описывает книги с полями: название, автор, дата публикации и цена.

Создание DjangoObjectType

Теперь мы создадим GraphQL-тип для этой модели. Откройте или создайте файл schema.py в вашем приложении:

# schema.py
import graphene
from graphene_django.types import DjangoObjectType
from .models import Book

class BookType(DjangoObjectType):
    class Meta:
        model = Book  # Указываем, с какой моделью связать этот тип
        fields = ("id", "title", "author", "published_date", "price")  # Явно перечисляем нужные поля

Здесь мы использовали DjangoObjectType, чтобы создать GraphQL-тип на основе модели Book. Поля модели автоматически преобразуются в поля GraphQL.

Подключение к Query

Теперь добавим этот новый тип в наши запросы (Query). Вот как это выглядит:

# schema.py (добавление Query)
class Query(graphene.ObjectType):
    all_books = graphene.List(BookType)  # Запрос, который возвращает список книг

    def resolve_all_books(root, info):
        # Этот метод отвечает за получение данных
        return Book.objects.all()

Свойство all_books добавляет возможность получить список всех книг. Функция resolve_all_books реализует логику получения данных из базы.

Настройка проекта

Не забудьте обновить schema.py проекта, чтобы связать эти запросы:

# core/schema.py (или в корне проекта, если вы используете схему на уровне всего проекта)
import graphene
import books.schema  # books — ваше приложение

class Query(books.schema.Query, graphene.ObjectType):
    pass

schema = graphene.Schema(query=Query)

Тестирование: получение данных через GraphQL

Теперь проверим, как работает наш API. Для этого поднимем сервер разработки:

python manage.py runserver

Откройте GraphiQL по адресу http://localhost:8000/graphql и выполните следующий запрос:

query {
  allBooks {
    id
    title
    author
    publishedDate
    price
  }
}

Вы должны получить все книги из базы данных. Как минимум, пустой список, если в базе ещё ничего нет.

Добавление новых возможностей

Представьте, что вас просят добавить возможность получать книги по их ID. Что ж, вызов принят!

Мы добавим новый запрос book, который будет принимать аргумент id. Вот пример реализации:

class Query(graphene.ObjectType):
    all_books = graphene.List(BookType)
    book = graphene.Field(BookType, id=graphene.Int(required=True))  # Новый запрос

    def resolve_all_books(root, info):
        return Book.objects.all()

    def resolve_book(root, info, id):
        # Ищем книгу по переданному ID
        try:
            return Book.objects.get(pk=id)
        except Book.DoesNotExist:
            return None

Теперь в GraphiQL можно выполнить такой запрос:

query {
  book(id: 1) {
    title
    author
    price
  }
}

Обратите внимание, что здесь мы добавили базовую обработку ошибок (если книги с указанным ID нет).

Ошибки и подводные камни

При работе с DjangoObjectType можно столкнуться с несколькими распространёнными проблемами.

Проблема 1: поле не отображается в GraphQL. Если вы добавили новое поле в модель, но оно не отображается в API, скорее всего, вы не упомянули это поле в fields класса Meta. Убедитесь, что оно явно перечислено.

Проблема 2: ошибка сериализации данных. Некоторые типы полей Django, например JSONField или FileField, могут вызывать ошибки, так как они не поддерживаются natively в GraphQL. Для таких случаев можно определить кастомное поле или преобразовать его в строку.

from django.db.models import JSONField

class MyModel(models.Model):
    data = JSONField()

class MyModelType(DjangoObjectType):
    class Meta:
        model = MyModel

    data_json = graphene.String()

    def resolve_data_json(root, info):
        return json.dumps(root.data)  # Преобразование JSON в строку

Практическое применение

Работа с моделями через GraphQL позволяет вам:

  • Быстро интегрировать существующие базы данных с новым API.
  • Гибко управлять запросами и фильтрацией данных на уровне типа.
  • Облегчить взаимодействие между фронтендом и бекендом.

Теперь вы можете разрабатывать более сложные запросы, обрабатывать входные данные и валидацию, а также оптимизировать взаимодействие с базой (например, через select_related() или prefetch_related()).

Совет: всегда тестируйте свои запросы в GraphiQL, чтобы убедиться, что они возвращают именно то, что вы ожидаете.

1
Задача
Модуль 3: Django, 24 уровень, 5 лекция
Недоступна
Создание GraphQL-схемы для модели
Создание GraphQL-схемы для модели
1
Задача
Модуль 3: Django, 24 уровень, 5 лекция
Недоступна
Добавление мутации для создания объекта
Добавление мутации для создания объекта
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ