Создайте блог с использованием Django, GraphQL и Vue
Оглавление
- Демонстрация: Администратор блога на Django, GraphQL API и интерфейс Vue
- Обзор проекта
- Предварительные условия
- Шаг 1: Настройка блога Django
- Шаг 2: Создайте администратора блога Django
- Шаг 3: Настройка Graphene-Django
- Шаг 4: Настройка django-cors-headers
- Шаг 5: Настройка Vue.js
- Шаг 6: Создайте базовые представления и компоненты
- Шаг 7: Обновите компоненты Vue
- Шаг 8: Внедрение Vue Apollo
- Шаг 9: Извлечение данных
- Следующие шаги
- Заключение
Вы регулярно пользуетесь Django? Вам не хочется разделить свой серверный и интерфейсный компоненты? Хотите ли вы управлять сохранением данных в API при отображении данных в одностраничном приложении (SPA) в браузере, используя JavaScript-фреймворк, такой как React или Vue?
Если вы ответили утвердительно на любой из этих вопросов, то вам повезло. В этом руководстве вы познакомитесь с процессом создания серверной части блога Django и интерфейса Vue, используя GraphQL для взаимодействия между ними.
Проекты - это эффективный способ изучения и закрепления концепций. Это учебное пособие структурировано в виде пошагового проекта, так что вы можете учиться на практике и делать перерывы по мере необходимости.
В этом руководстве вы узнаете, как:
- Переведите ваши модели Django в GraphQL API
- Запустите сервер Django и приложение Vue на вашем компьютере одновременно
- Администрируйте свои записи в блоге с помощью администратора Django
- Использовать GraphQL API в Vue для отображения данных в браузере
Демонстрация: администратор блога на Django, GraphQL API и интерфейс Vue
Приложения для блогов - это обычный стартовый проект, поскольку они включают в себя операции создания, чтения, обновления и удаления (CRUD). В этом проекте вы будете использовать администратора Django для выполнения тяжелой работы и сосредоточитесь на предоставлении GraphQL API для данных вашего блога.
Вы будете использовать Vue.js 3 и его composition API для интерфейса вашего блога. Vue позволяет довольно легко создавать динамические интерфейсы благодаря реактивной привязке данных и простым в управлении компонентам. Кроме того, поскольку вы имеете дело с данными из GraphQL API, вы можете использовать плагин Vue Apollo.
Далее вы убедитесь, что у вас есть вся необходимая справочная информация и инструменты, прежде чем приступать к созданию своего приложения для ведения блога.
Обзор проекта
Для этого проекта вы создадите небольшое приложение для ведения блога с некоторыми элементарными функциями:
- Авторы могут написать много постов.
- Сообщения могут иметь множество тегов и могут быть как опубликованными, так и неопубликованными.
Вы создадите серверную часть этого блога на Django, в комплекте с администратором для добавления нового контента в блог. Затем вы предоставите данные контента в виде GraphQL API и используете Vue для отображения этих данных в браузере.
Вы выполните это в несколько этапов высокого уровня. В конце каждого шага вы найдете ссылку на исходный код для данного этапа проекта.
Если вам интересно, как выглядит исходный код для каждого шага, то вы можете перейти по ссылке ниже:
Получите свой код: Нажмите здесь, чтобы загрузить бесплатный образец кода, который вы будете использовать для создания блога с использованием Django, GraphQL, и Vue.
Предварительные условия
Вы будете лучше подготовлены к этому уроку, если у вас уже есть солидный опыт работы с некоторыми концепциями веб-приложений. Вы должны понимать, как работают HTTP-запросы и ответы и API. Вы можете ознакомиться с Python и API: выигрышная комбинация для чтения общедоступных данных, чтобы понять подробности использования GraphQL API в сравнении с REST API.
Поскольку вы будете использовать Django для создания серверной части вашего блога, вам следует ознакомиться с запуском проекта на Django и настройкой администратора на Django. Если вы раньше редко использовали Django, возможно, вы также захотите сначала попробовать создать другой проект, работающий только на Django. Для получения более подробного ознакомления ознакомьтесь с Начало работы с Django, часть 1: Создание приложения для портфолио..
И поскольку вы будете использовать Vue во внешнем интерфейсе, вам также поможет некоторый опыт работы с JavaScript. Если в прошлом вы использовали только JavaScript-фреймворк, такой как jQuery, то Введение в Vue станет хорошей основой.
Знакомство с JSON также важно, поскольку запросы GraphQL похожи на JSON и возвращают данные в формате JSON. Вы можете прочитать о Работе с данными JSON в Python для ознакомления.
Шаг 1: Настройка блога Django
Прежде чем заходить слишком далеко, вам понадобится каталог, в котором вы сможете упорядочить код для своего проекта. Откройте новый сеанс терминала и перейдите в папку в вашей операционной системе, где вы храните свои проекты. Затем создайте новый каталог проектов. Например, dvg/
, что является сокращением от Django-Vue-GraphQL:
$ mkdir dvg/
$ cd dvg/
Вам также придется полностью разделить интерфейсный и серверный код, поэтому рекомендуется сразу же создать это разделение. Создайте каталог back_end/
внутри каталога вашего проекта:
$ mkdir back_end/
$ cd back_end/
Вы разместите свой код Django в этом каталоге, чтобы он был полностью изолирован от кода интерфейса Vue, который вы создадите позже в этом руководстве.
Установить Django
Теперь вы готовы приступить к созданию приложения Django. Чтобы отделить зависимости для этого проекта от других ваших проектов, создайте виртуальную среду, в которой вы будете устанавливать требования вашего проекта.
В вашем терминале убедитесь, что вы находитесь внутри папки back_end/
, которую вы только что создали. Затем выберите свою операционную систему ниже и используйте команду, зависящую от вашей платформы, для настройки виртуальной среды :
PS> python -m venv venv
PS> .\venv\Scripts\activate
(venv) PS>
$ python -m venv venv
$ source venv/bin/activate
(venv) $
С помощью приведенных выше команд вы создаете и активируете виртуальную среду с именем venv
, используя встроенный в Python модуль venv
. Надпись в скобках (venv)
перед приглашением означает, что вы успешно активировали виртуальную среду.
Примечание: В остальной части руководства предполагается, что вы будете выполнять команды, связанные с Python и Django, в вашей активной виртуальной среде.
Теперь, когда у вас есть виртуальная среда для установки требований, создайте файл requirements.txt
в каталоге back_end/
и определите первое необходимое вам требование:
(venv) $ echo "Django==5.0.2" > requirements.txt
Как только вы создадите файл requirements.txt
, используйте его для установки Django:
(venv) $ python -m pip install -r requirements.txt
Теперь вы готовы приступить к созданию своего проекта на Django.
Создайте проект Django
Теперь, когда Django установлен, используйте команду django-admin
для инициализации вашего проекта Django:
(venv) $ django-admin startproject backend .
Не забудьте добавить точку (.
) в конце приведенной выше команды. Точка не позволяет Django создавать вложенный каталог проектов для вашего проекта backend
.
Примечание: Называя проект Django backend
, вы указываете цель проекта Django. Но поскольку вы уже работаете с папкой back_end/
, вы называете папку проекта Django backend/
без символа подчеркивания (_
), чтобы различать эти папки.
На этом этапе структура каталогов вашего проекта должна выглядеть следующим образом:
dvg/
└── back_end/
├── manage.py
├── requirements.txt
└── backend/
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
В корневом каталоге вашего проекта dvg/
есть папка back_end/
, которая содержит ваш проект Django. Внутри back_end/
находится папка backend/
, файл manage.py
и файл requirements.txt
. В дереве каталогов выше не показана папка venv/
для вашей виртуальной среды.
Запуск миграции Django
Прежде чем вы добавите что-либо конкретное в свое приложение, пришло время выполнить первоначальную миграцию Django . Если вы раньше не сталкивались с миграциями, ознакомьтесь с Миграциями Django: руководство по эксплуатации. Запустите миграцию с помощью migrate
команды управления:
(venv) $ python manage.py migrate
Вы должны увидеть длинный список миграций, после каждой из которых стоит OK
:
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
При запуске миграции Django также будет создан SQLite файл с именем db.sqlite3
. Это база данных вашего проекта. Как следует из названия, в ней будут храниться данные для вашего проекта. Все записи в блоге, которые вы создадите во время урока, будут сохранены в этом файле.
Создайте суперпользователя
Теперь, когда у вас есть база данных, вы можете создать суперпользователя. Этот пользователь понадобится вам, чтобы в конечном итоге войти в интерфейс администратора Django. Используйте команду управления createsuperuser
, чтобы создать ее:
(venv) $ python manage.py createsuperuser
При выполнении команды управления createsuperuser
вам будет предложено выбрать имя пользователя, указать адрес электронной почты и установить пароль. Используйте свои собственные данные для заполнения этих полей и обязательно запомните их. Эти учетные данные понадобятся вам для быстрого входа в интерфейс администратора Django.
Краткое описание шага 1
Теперь, когда вы установили Django, создали проект Django, запустили миграции Django и создали суперпользователя, у вас есть полностью функционирующее приложение Django. Теперь вы сможете запустить сервер разработки Django и просмотреть его в своем браузере. Запустите сервер с помощью команды управления runserver
, которая по умолчанию будет прослушивать порт 8000
:
(venv) $ python manage.py runserver
Затем перейдите на страницу http://localhost:8000
в вашем браузере. Вы должны увидеть всплывающую страницу Django, указывающую на то, что установка прошла успешно:
Вы также должны иметь возможность посетить http://localhost:8000/admin
, где вы увидите форму входа в систему:
Используйте имя пользователя и пароль, которые вы ввели для своего суперпользователя, чтобы войти в систему администратора Django. Если все работает, вы попадете в интерфейс администратора Django. На данный момент эта страница будет довольно пустой, но на следующем шаге вы сделаете ее намного интереснее.
Получите свой код: Нажмите здесь, чтобы загрузить бесплатный образец кода, который вы будете использовать для создания блога с использованием Django, GraphQL, и Vue.
Шаг 2: Создайте администратора блога Django
Теперь, когда у вас есть основы вашего проекта на Django, вы готовы приступить к созданию основной логики для вашего блога. На этом шаге вы создадите модели данных и административную конфигурацию для создания контента блога и управления им.
Создайте приложение для блога на Django
Имейте в виду, что один проект на Django может содержать множество приложений на Django. Вам следует выделить поведение вашего блога в отдельное приложение на Django, чтобы оно отличалось от любых будущих приложений, которые вы будете встраивать в свой проект. Создайте приложение, используя команду управления startapp
:
(venv) $ python manage.py startapp blog
При этом будет создан каталог blog/
с несколькими файлами, аналогичными тем, которые у вас уже есть в backend/
:
dvg/
└── back_end/
├── manage.py
├── requirements.txt
├── db.sqlite3
├── backend/
│ └── ...
└── blog/
├── __init__.py
├── admin.py
├── apps.py
├── migrations/
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
В некоторые из этих файлов вы внесете изменения и дополнения позже в этом руководстве. Сначала вам необходимо внести некоторые коррективы в backend/
приложение project.
Включить приложение Django Blog
Создание приложения Django не делает его доступным в вашем проекте по умолчанию. Чтобы убедиться, что проект знает о вашем новом приложении blog
, вам нужно добавить его в список установленных приложений. Обновите переменную INSTALLED_APPS
в backend/settings.py
:
back_end/backend/settings.py
# ...
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"blog.apps.BlogConfig",
]
# ...
Добавления "blog"
в список INSTALLED_APPS
достаточно, чтобы сообщить Django о приложении. Если вы явно укажете на класс конфигурации вашего приложения, то INSTALLED_APPS
поможет Django найти информацию о вашем приложении, такую как модели данных и шаблоны URL, которые оно может содержать.
Создайте модели данных блога Django
Теперь, когда Django может обнаружить ваше blog
приложение, вы можете создать модели данных. Для начала вы создадите три модели:
Profile
хранит дополнительную информацию о пользователях блога.Tag
представляет категорию, в которую можно группировать записи в блоге.Post
хранит содержимое и метаданные каждой записи в блоге.
Вы добавите каждую из этих моделей в blog/models.py
. Каждая из ваших моделей будет наследоваться от класса models.Model
Django.
Модель Profile
Модель Profile
будет содержать три поля, содержащие информацию о пользователе:
user
это однозначная связь с пользователем Django, с которым связан профиль.website
это необязательный URL-адрес, по которому вы можете узнать больше о пользователе.bio
это необязательный краткий текст о пользователе.
Откройте blog/models.py
и добавьте импорт для модуля settings
:
back_end/blog/models.py
from django.db import models
from django.conf import settings
Затем создайте модель Profile
, которая должна выглядеть следующим образом:
back_end/blog/models.py
from django.db import models
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.PROTECT,
)
website = models.URLField(blank=True)
bio = models.CharField(max_length=240, blank=True)
def __str__(self):
return self.user.get_username()
Метод .__str__()
заставит создаваемые вами объекты Profile
отображать имя пользователя на сайте администратора.
Модель Tag
При создании записи в блоге вы сможете добавлять к ней теги. Эти теги позволят вашим читателям позже фильтровать записи в блоге по определенному тегу.
Модель Tag
содержит только одно поле, name
, в котором хранится краткое уникальное имя тега. Создайте модель Tag
, которая должна выглядеть следующим образом:
back_end/blog/models.py
# ...
class Tag(models.Model):
name = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.name
Опять же, .__str__()
приведет к тому, что Tag
создаваемые вами объекты будут отображаться в более удобном для пользователя виде на сайте администратора.
Модель Post
Сердцем и центральной частью любого блога являются записи в блоге. Модель Post
является наиболее сложной, поскольку она представляет собой фактическую запись в блоге с содержанием, которое вы пишете, и метаинформацией, которую вы добавляете. В нем будет несколько полей:
Имя поля | Цель |
---|---|
title |
Уникальное название поста, которое будет показано читателям. |
subtitle |
Необязательное пояснение содержания поста, помогающее читателям решить, хотят ли они его читать. |
slug |
Уникальный, читаемый идентификатор поста для использования в URL-адресах. |
body |
Содержание поста |
meta_description |
Необязательное описание для использования в поисковых системах, таких как Google. |
date_created |
Временная метка создания поста |
date_modified |
Временная метка последнего редактирования поста |
publish_date |
Необязательная временная метка, когда пост будет опубликован |
published |
Показывает, доступна ли запись читателям в данный момент. |
author |
Ссылка на профиль пользователя, написавшего пост |
tags |
Список тегов, связанных с постом, если таковые имеются |
Поскольку в блогах обычно первыми отображаются самые свежие записи, вы также захотите, чтобы ordering
указывалось по дате публикации, то есть сначала отображались самые свежие. Создайте модель Post
, которая должна выглядеть следующим образом:
back_end/blog/models.py
# ...
class Post(models.Model):
title = models.CharField(max_length=255, unique=True)
subtitle = models.CharField(max_length=255, blank=True)
slug = models.SlugField(max_length=255, unique=True)
body = models.TextField()
meta_description = models.CharField(max_length=150, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
publish_date = models.DateTimeField(blank=True, null=True)
published = models.BooleanField(default=False)
author = models.ForeignKey(Profile, on_delete=models.PROTECT)
tags = models.ManyToManyField(Tag, blank=True)
class Meta:
ordering = ["-publish_date"]
Аргумент on_delete=models.PROTECT
для author
гарантирует, что вы случайно не удалите автора, у которого все еще есть записи в блоге. Связь ManyToManyField
с Tag
позволяет связать запись с нулем или более тегов. Каждый тег может быть связан со многими записями.
Создайте конфигурацию администратора модели
Теперь, когда ваши модели готовы, вам нужно указать Django, как они должны отображаться в интерфейсе администратора. В blog/admin.py
начните с импорта модуля admin
Django и ваших моделей:
back_end/blog/admin.py
from django.contrib import admin
from blog.models import Post, Profile, Tag
Затем создайте и зарегистрируйте классы администратора для Profile
и Tag
, для которых необходимо указать только model
:
back_end/blog/admin.py
from django.contrib import admin
from blog.models import Post, Profile, Tag
@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
model = Profile
@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
model = Tag
Как и в случае с model, класс admin для Post
более задействован. Сообщения содержат много информации, поэтому важно более тщательно выбирать, какую информацию отображать, чтобы не перегружать интерфейс:
back_end/blog/admin.py
# ...
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
model = Post
list_display = (
"id",
"title",
"subtitle",
"slug",
"publish_date",
"published",
)
list_filter = (
"published",
"publish_date",
)
list_editable = (
"title",
"subtitle",
"slug",
"publish_date",
"published",
)
search_fields = (
"title",
"subtitle",
"slug",
"body",
)
prepopulated_fields = {
"slug": (
"title",
"subtitle",
)
}
date_hierarchy = "publish_date"
save_on_top = True
Чтобы упростить просмотр и редактирование записей, вы настраиваете сведения о записи с помощью следующих специальных переменных:
list_display
: Показывайте только конкретную информацию о каждом сообщении.list_filter
: Разрешить фильтрацию списка записей по опубликованным или неопубликованным записям, а также по дате публикации.list_editable
: Разрешить редактирование всех отображаемых полей, за исключением идентификатора.search_fields
: Разрешить поиск записей по заголовку, подзаголовку, вставке и тексту сообщения.prepopulated_fields
: Предварительно заполните поле slug, используя поля title и subtitle.date_hierarchy
: Используйте дату публикации всех записей, чтобы создать доступную для просмотра иерархию дат.save_on_top
: Отобразите кнопку в верхней части списка для сохранения изменений.
Подробнее обо всех возможностях, которые может предложить администратор Django, вы можете прочитать в Настройка администратора Django с помощью Python.
Создайте миграции модели
В Django есть вся информация, необходимая для администрирования и сохранения содержимого вашего блога, но вам потребуется обновить базу данных, чтобы поддерживать эти изменения. Ранее в этом руководстве вы выполняли миграцию встроенных моделей в Django. Теперь вы создадите и запустите миграции для своих моделей.
Сначала создайте миграции, используя команду управления makemigrations
:
(venv) $ python manage.py makemigrations
Migrations for 'blog':
blog/migrations/0001_initial.py
- Create model Tag
- Create model Profile
- Create model Post
При этом создается миграция, имя которой по умолчанию 0001_initial.py
. Запустите эту миграцию с помощью команды управления migrate
:
(venv) $ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
Applying blog.0001_initial... OK
Теперь у вас есть все ваши модели данных, и вы настроили администратора Django таким образом, чтобы вы могли добавлять и редактировать эти модели.
Начните вести блог
Запустите сервер разработки Django заново, если вы остановили его перед выполнением миграции. Затем перейдите в интерфейс администратора по адресу http://localhost:8000/admin
и узнайте, что изменилось.
Вы должны увидеть ссылки на список тегов, профилей и записей, а также ссылки для добавления или редактирования каждой из них. Попробуйте добавить свои собственные записи прямо сейчас и отредактировать несколько, чтобы увидеть реакцию интерфейса администратора:
Прежде чем вы перейдете к следующим шагам, в вашем блоге должно быть сохранено около трех записей. Убедитесь, что к ним также прикреплено несколько тегов.
Краткое описание шага 2
На данный момент вы завершили достаточно работы над серверной частью, чтобы можно было с головой уйти в развитие Django. Вы могли бы использовать механизм маршрутизации URL-адресов и создания шаблонов в Django для создания страниц, которые будут показывать читателям весь контент, который вы создаете в admin.
Вместо этого вы создадите серверную часть в виде GraphQL API, чтобы в конечном итоге использовать ее из браузера и обеспечить более богатый опыт работы на стороне клиента.
Получите свой код: Нажмите здесь, чтобы загрузить бесплатный образец кода, который вы будете использовать для создания блога с использованием Django, GraphQL, и Vue.
Шаг 3: Настройка Graphene-Django
GraphQL позволяет извлекать только те данные, которые вам нужны, что может быть полезно по сравнению с очень большими ответами, которые часто используются в RESTful API. GraphQL также обеспечивает большую гибкость при проектировании данных, поэтому вы часто можете извлекать данные новыми способами, не меняя логику сервиса, предоставляющего GraphQL API.
Вы будете использовать Graphene-Django для интеграции того, что вы уже создали, в GraphQL API.
Установить Graphene-Django
Чтобы начать работу с Graphene-Django, сначала добавьте его в файл требований к вашему проекту:
back_end/backend/requirements.txt
Django==5.0.2
graphene-django==3.2.0
Затем установите его, используя обновленный файл требований:
(venv) $ python -m pip install -r requirements.txt
Добавьте "graphene_django"
в переменную INSTALLED_APPS
в модуле settings.py
вашего проекта, чтобы Django нашел ее:
back_end/backend/settings.py
# ...
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"blog.apps.BlogConfig",
"graphene_django",
]
# ...
После установки сторонних приложений Django, таких как Graphene-Django, с помощью pip
, вам необходимо добавить их в свой проект, указав в INSTALLED_APPS
. Теперь, когда Django знает о "graphene_django"
, вам нужно выполнить некоторую настройку.
Настройка Graphene-Django
Чтобы заставить Graphene-Django работать в вашем проекте, вам нужно настроить несколько компонентов:
- Обновите
settings.py
, чтобы проект знал, где искать информацию о GraphQL. - Добавьте шаблон URL-адреса для обслуживания GraphQL API и GraphiQL, удобного для изучения интерфейса GraphQL.
- Создайте схему GraphQL, чтобы Graphene-Django знал, как перевести ваши модели в GraphQL.
Обновить настройки Django
Параметр GRAPHENE
настраивает Graphene-Django на поиск вашей схемы GraphQL в определенном месте. В settings.py
укажите SCHEMA
на blog.schema.schema
путь к Python, который вы вскоре создадите:
back_end/backend/settings.py
# ...
GRAPHENE = {
"SCHEMA": "blog.schema.schema",
}
Обратите внимание, что это дополнение может привести к тому, что Django выдаст ошибку импорта, которую вы устраните при создании своей схемы GraphQL.
Добавить шаблон URL-адреса для GraphQL и GraphiQL
Чтобы Django мог обслуживать конечную точку GraphQL и интерфейс GraphiQL, вы добавите новый шаблон URL-адреса в backend/urls.py
. Вы укажете URL-адрес на GraphQLView
в Graphene-Django. Поскольку вы не используете функции защиты от подделки межсайтовых запросов (CSRF) движка шаблонов Django , вам также потребуется импортировать декоратор Django csrf_exempt
, чтобы пометить представление как освобожденное от защиты CSRF:
back_end/backend/urls.py
from django.contrib import admin
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView
urlpatterns = [
path("admin/", admin.site.urls),
path("graphql/", csrf_exempt(GraphQLView.as_view(graphiql=True))),
]
Аргумент graphiql=True
указывает Graphene-Django сделать графический интерфейс доступным.
Создайте схему GraphQL
Теперь вы создадите схему GraphQL, которая должна быть похожа на конфигурацию администратора, созданную вами ранее. Схема состоит из нескольких классов, каждый из которых связан с определенной моделью Django, и одного, который определяет, как разрешать несколько важных типов запросов, которые вам понадобятся во внешнем интерфейсе.
Создайте новый модуль schema.py
в каталоге blog/
. Импортируйте модели Graphene-Django DjangoObjectType
, ваши blog
и get_user_model()
, что даст вам доступ к модели Django User
:
back_end/blog/schema.py
from django.contrib.auth import get_user_model
from graphene_django import DjangoObjectType
from blog import models
Затем создайте соответствующий класс для каждой из ваших моделей и модели User
. У каждого из них должно быть имя, заканчивающееся на Type
, поскольку каждое из них представляет тип GraphQL. Ваши классы должны выглядеть следующим образом:
back_end/blog/schema.py
# ...
class UserType(DjangoObjectType):
class Meta:
model = get_user_model()
class AuthorType(DjangoObjectType):
class Meta:
model = models.Profile
class PostType(DjangoObjectType):
class Meta:
model = models.Post
class TagType(DjangoObjectType):
class Meta:
model = models.Tag
Кроме того, вам нужен класс Query
, который наследуется от graphene.ObjectType
. Этот класс объединит все созданные вами классы типов. Чтобы настроить это, импортируйте graphene
и добавьте методы в Query
, чтобы указать, как можно запрашивать ваши модели:
back_end/blog/schema.py
1import graphene
2from django.contrib.auth import get_user_model
3from graphene_django import DjangoObjectType
4
5from blog import models
6
7# ...
8
9class Query(graphene.ObjectType):
10 all_posts = graphene.List(PostType)
11 author_by_username = graphene.Field(AuthorType, username=graphene.String())
12 post_by_slug = graphene.Field(PostType, slug=graphene.String())
13 posts_by_author = graphene.List(PostType, username=graphene.String())
14 posts_by_tag = graphene.List(PostType, tag=graphene.String())
15
16 def resolve_all_posts(root, info):
17 return (
18 models.Post.objects.prefetch_related("tags")
19 .select_related("author")
20 .all()
21 )
22
23 def resolve_author_by_username(root, info, username):
24 return models.Profile.objects.select_related("user").get(
25 user__username=username
26 )
27
28 def resolve_post_by_slug(root, info, slug):
29 return (
30 models.Post.objects.prefetch_related("tags")
31 .select_related("author")
32 .get(slug=slug)
33 )
34
35 def resolve_posts_by_author(root, info, username):
36 return (
37 models.Post.objects.prefetch_related("tags")
38 .select_related("author")
39 .filter(author__user__username=username)
40 )
41
42 def resolve_posts_by_tag(root, info, tag):
43 return (
44 models.Post.objects.prefetch_related("tags")
45 .select_related("author")
46 .filter(tags__name__iexact=tag)
47 )
Класс Query
в строке 9 состоит из ряда атрибутов, которые являются либо graphene.List
, либо graphene.Field
. Вы используете graphene.Field
, если запрос должен вернуть один элемент, и graphene.List
, если он вернет несколько элементов.
Для каждого из этих атрибутов вы также создаете метод для разрешения запроса:
- Строка 16: Получите все сообщения.
- Строка 23: Получаем автора с заданным именем пользователя.
- Строка 28: Получаем сообщение с заданным фрагментом.
- Строка 35: Получать все сообщения данного автора.
- Строка 42: Получать все сообщения с заданным тегом.
Вы разрешаете запрос, используя информацию, указанную в запросе, и возвращая в ответ соответствующий набор запросов Django.
Примечание: Метод для каждого распознавателя должен начинаться с resolve_
, а остальная часть имени должна соответствовать соответствующему атрибуту. В качестве примера, метод для разрешения набора запросов для атрибута all_posts
в строке 16 должен быть назван resolve_all_posts
.
Теперь у вас есть все типы и средства преобразования для вашей схемы, но помните, что переменная GRAPHENE
, которую вы создали в backend/settings.py
, указывает на blog.schema.schema
. Создайте переменную schema
в конце schema.py
, которая преобразует ваш класс Query
в graphene.Schema
, чтобы связать все это вместе:
back_end/blog/schema.py
# ...
schema = graphene.Schema(query=Query)
Эта переменная соответствует значению "blog.schema.schema"
, которое вы настроили для Graphene-Django ранее в этом руководстве.
Краткое описание шага 3
Вы доработали модель данных вашего блога, а теперь еще и обернули ее с помощью Graphene-Django, чтобы использовать эти данные в качестве GraphQL API.
Запустите сервер разработки Django и посетите http://localhost:8000/graphql
:
Вы должны увидеть графический интерфейс с комментариями, объясняющими, как пользоваться инструментом.
Разверните раздел Документы в левом верхнем углу экрана и нажмите запрос: запросить. Вы должны увидеть все запросы и типы, которые вы настроили в своей схеме:
Если вы еще не создали тестовый контент для блога, сделайте это сейчас. Попробуйте выполнить следующий запрос, который должен вернуть список всех созданных вами записей:
{
allPosts {
title
author {
user {
username
}
}
tags {
name
}
}
}
В ответе должен быть возвращен список записей. Структура каждой записи должна соответствовать форме запроса, как в следующем примере:
{
"data": {
"allPosts": [
{
"title": "The Art of the Perfect Nap",
"author": {
"user": {
"username": "frieda"
}
},
"tags": [
{
"name": "Self Care"
},
{
"name": "DogLife"
}
]
},
{
"title": "The Unbearable Lightness of Being Groomed",
"author": {
"user": {
"username": "frieda"
}
},
"tags": [
{
"name": "DogLife"
},
{
"name": "Grooming"
}
]
},
{
"title": "Confessions of an Office Dog: The WFH Chronicles",
"author": {
"user": {
"username": "frieda"
}
},
"tags": [
{
"name": "DogLife"
},
{
"name": "Work"
}
]
}
]
}
}
Полученный вами ответ должен соответствовать публикациям, которые вы уже создали. Если вы сохранили несколько сообщений и видите их в ответе, значит, вы готовы продолжить.
Получите свой код: Нажмите здесь, чтобы загрузить бесплатный образец кода, который вы будете использовать для создания блога с использованием Django, GraphQL, и Vue.
Шаг 4: Настройка django-cors-headers
Вам нужно будет сделать еще один шаг, прежде чем вы сможете завершить работу с серверной частью. Поскольку серверная и интерфейсная части будут локально работать на разных портах, а в рабочей среде они могут выполняться в совершенно разных доменах, применяется совместное использование ресурсов разных источников (CORS). Без обработки CORS запросы от интерфейса к серверной части, как правило, блокируются вашим браузером.
Проект django-cors-headers
позволяет работать с CORS довольно безболезненно. Вы будете использовать это, чтобы указать Django отвечать на запросы, даже если они поступают из другого источника, что позволит интерфейсу должным образом взаимодействовать с GraphQL API.
Установить django-cors-headers
Сначала добавьте django-cors-headers
в свой файл требований:
back_end/backend/requirements.txt
Django==5.0.2
graphene-django==3.2.0
django-cors-headers==4.3.1
Затем установите его, используя обновленный файл требований:
(venv) $ python -m pip install -r requirements.txt
Добавьте "corsheaders"
в список INSTALLED_APPS
в модуле settings.py
вашего проекта:
back_end/backend/settings.py
# ...
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"blog.apps.BlogConfig",
"graphene_django",
"corsheaders",
]
# ...
Оставайтесь в settings.py
и добавьте "corsheaders.middleware.CorsMiddleware"
в начало списка MIDDLEWARE
:
back_end/backend/settings.py
# ...
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
# ...
В документации django-cors-headers
предлагается размещать промежуточное программное обеспечение как можно раньше в списке MIDDLEWARE
. Если вы не хотите размещать промежуточное программное обеспечение CORS в самом начале списка, то вам нужно, по крайней мере, убедиться, что оно находится перед программным обеспечением Django CommonMiddleware
.
Настройка django-cors-headers
CORS существует не просто так. Вы не хотите раскрывать свое приложение, чтобы им можно было пользоваться из любой точки Интернета. Чтобы определить, насколько вы хотите открыть GraphQL API, вы должны использовать один из этих трех параметров:
CORS_ALLOWED_ORIGINS
: Список доменов, с которых ваше приложение Django будет разрешать запросы.CORS_ALLOWED_ORIGIN_REGEXES
: Список регулярных выражений, соответствующих доменам, из которых разрешаются запросы.CORS_ALLOW_ALL_ORIGINS
: Логическое значение, определяющее, должен ли Django быть полностью открыт или полностью закрыт по умолчанию.
Для этого проекта достаточно CORS_ALLOWED_ORIGINS
. Добавьте следующие настройки в settings.py
:
back_end/backend/settings.py
# ...
CORS_ALLOWED_ORIGINS = ["http://localhost:5173"]
Этот параметр разрешает запросы только с вашего интерфейса, который вы создадите позже и который будет выполняться на порту 5173
локально.
Краткое описание шага 4
Поздравляем, вы завершили разработку серверной части своего блога! У вас есть рабочая модель данных, рабочий интерфейс администратора, работающий GraphQL API, который вы можете изучить с помощью GraphiQL, и возможность запрашивать API из интерфейса, который вы создадите в следующий раз. Это отличное место для того, чтобы сделать паузу, если вы давно не делали перерыв.
Получите свой код: Нажмите здесь, чтобы загрузить бесплатный образец кода, который вы будете использовать для создания блога с использованием Django, GraphQL, и Vue.
Шаг 5: Настройка Vue.js
Вы будете использовать Vue в качестве интерфейса для вашего блога. Чтобы настроить Vue, вам необходимо установить Node.js в вашей системе, а затем создать проект Vue. В своем проекте вы установите пару важных плагинов и запустите другой сервер разработки, чтобы убедиться, что ваше приложение и его зависимости работают должным образом.
Установить Node.js
Прежде чем вы сможете работать с Vue, вы должны установить Node.js. Node.js это среда выполнения JavaScript, которая позволяет запускать JavaScript вне вашего браузера.
Точно так же, как Python и pip
, Node.js предоставляет менеджер пакетов. Диспетчер пакетов узлов называется npm, и вскоре вы будете использовать его для установки Vue и некоторых дополнительных плагинов.
Примечание: Пожалуйста, перейдите на официальную страницу загрузки Node.js, чтобы загрузить и установить Node.js в свою операционную систему, прежде чем продолжить изучение этого руководства.
Чтобы убедиться, что Node.js и npm доступны в вашей операционной системе, откройте новое окно терминала и проверьте их версии с помощью следующих команд:
$ node -v
v20.11.1
$ npm -v
10.2.4
Как только вы убедитесь, что Node.js и npm присутствуют, оставьте окно вашего терминала открытым и перейдите в каталог вашего проекта:
$ cd dvg/
Каталог dvg/
является отправной точкой для инициализации вашего проекта Vue.
Создайте проект Vue
Как и команда startproject
в Django, инструмент create-vue
помогает вам создать структуру вашего проекта. Более того, он задает вам множество вопросов для точной настройки настроек. Если вы хотите внимательно следить за ходом выполнения этого руководства, то вам следует ответить на следующие вопросы:
Prompt | Selection |
---|---|
Project name: | front_end |
Add TypeScript? | No |
Add JSX Support? | No |
Add Vue Router for Single Page Application development? | Yes |
Add Pinia for state management? | No |
Add Vitest for Unit Testing? | No |
Add an End-to-End Testing Solution? | No |
Add ESLint for code quality? | No |
Наиболее важными параметрами являются присвоение вашему проекту названия “front_end” и добавление в проект маршрутизатора Vue.
Чтобы запустить процесс создания каркасов, запустите эту команду в каталоге вашего проекта:
$ npm create vue@latest
Need to install the following packages:
create-vue@3.9.2
Ok to proceed? (y) y
После того, как вы запустили процесс, вам необходимо установить инструмент create-vue
. Затем вам нужно ответить на несколько вопросов об инструментах вашего проекта Vue. Опять же, не забудьте указать название вашего проекта “front_end” и добавить Vue Router в проект
В процессе создания каркаса создается каталог front_end/
рядом с вашим существующим каталогом back_end/
, устанавливается ряд зависимостей JavaScript и создаются некоторые файлы-скелеты для приложения:
front_end/
│
├── public/
│ └── ...
│
├── src/
│ │
│ ├── assets/
│ │ └── ...
│ │
│ ├── components/
│ │ └── ...
│ │
│ ├── router/
│ │ └── index.js
│ │
│ ├── views/
│ │ ├── AboutView.vue
│ │ └── HomeView.vue
│ │
│ ├── App.vue
│ └── main.js
│
├── README.md
├── index.html
├── jsconfig.json
├── package.json
└── vite.config.js
В дополнение к файлам и папкам, показанным выше, вы также можете найти папку .vscode/
с рекомендуемыми расширениями Visual Studio Code и файл .gitignore
который содержит некоторые файлы по умолчанию, которые вы, возможно, захотите игнорировать при работе с Git.
Краткое описание шага 5
Папка front_end/
будет корневой папкой для интерфейсной части вашего проекта. Все последующие команды вы будете запускать из этого каталога или его вложенных папок.
Перейдите в папку front_end/
и установите все зависимости для вашего проекта Vue:
$ cd front_end
$ npm install --include dev
added 30 packages, and audited 31 packages in 7s
...
found 0 vulnerabilities
Обязательно добавьте флаг --include dev
в команду npm install
, чтобы также установить зависимости разработки, такие как Vite. После создания структуры вашего проекта и установки всех зависимостей вы можете запустить сервер разработки Vote:
$ npm run dev
> front_end@0.0.0 dev
> vite
VITE v5.1.4 ready in 333 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
По умолчанию ваш видеосервер работает на порту 5173
. Если этот порт уже используется, Vite ищет другой порт. В этом случае вы получите сообщение на выходе терминала.
Примечание: Если ваш видеосервер работает на другом порту, вам необходимо изменить URL-адрес, указанный для CORS_ALLOWED_ORIGINS
в settings.py
вашего Проект Django.
Теперь ваше приложение Django запущено по адресу http://localhost:8000
, а приложение Vue - по адресу http://localhost:5173
. Теперь перейдите по ссылке http://localhost:5173
в вашем браузере:
Вы должны увидеть всплывающую страницу Vue, которая указывает на то, что вы все успешно установили. Если вы видите всплывающую страницу, значит, вы готовы приступить к созданию некоторых своих собственных представлений и компонентов.
Получите свой код: Нажмите здесь, чтобы загрузить бесплатный образец кода, который вы будете использовать для создания блога с использованием Django, GraphQL, и Vue.
Шаг 6: Создайте базовые представления и компоненты
Теперь, когда Vue запущен, вы можете приступить к созданию компонентов. Компоненты - это строительные блоки для вашего интерфейса:
Компоненты позволяют нам разделить пользовательский интерфейс на независимые части, которые можно использовать повторно, и рассматривать каждую часть отдельно. Обычно приложение организовано в виде дерева вложенных компонентов. (Источник)
Компоненты, которые вы создадите в первую очередь, - это просмотры для просмотра ваших сообщений и авторов. Просмотры - это файлы, которые вы позже загрузите вместе с вашими маршрутами. Прежде чем вы создадите свои первые просмотры, необходимо немного навести порядок.
Удалить существующие представления
Инструмент create-vue
полезен для создания структуры вашего проекта. Он создает файлы, которые могут стать хорошей отправной точкой для создания ваших собственных файлов проекта Vue. Чтобы вы не перепутали свои новые файлы с существующими, рекомендуется сначала очистить проект.
Примечание: Пока вы очищаете свой проект Vue и работаете с новыми файлами, видеосервер будет выдавать некоторые ошибки. Пока вы можете не обращать на них внимания. В конце этого шага все будет настроено таким образом, чтобы сервер Vite снова работал без ошибок.
В каталоге src/views/
есть два представления по умолчанию, которые необходимо удалить:
HomeView.vue
AboutView.vue
Удалив оба файла, вы можете сохранить их в том же каталоге. В каталоге src/views/
вы будете создавать свои представления в следующий раз.
Добавляйте свои просмотры
У вашего блога будет четыре вида. Начните с AuthorView.vue
. Этот файл представляет собой однофайловый компонент Vue (SFC). SFC-файлы содержат блоки HTML, JavaScript и CSS, которые объединяют представление, логику и стиль:
front_end/src/views/AuthorView.vue
<script setup>
import PostList from "../components/PostList.vue";
</script>
<template>
<h2>Author</h2>
<PostList />
</template>
<style scoped>
h2 {
color: red;
}
</style>
Вы можете расположить блоки так, как вам нравится. Но обычно вы начинаете с блока <script>
. Здесь вы импортируете все компоненты, которые использует ваш SFC. В данном случае это PostList
компонент, который вы создадите позже.
HTML-код должен быть помещен внутри блока <template>
. Для компонентов, которые вы хотите отобразить, используйте пользовательские HTML-теги.
CSS внутри <style>
имеет область действия. Это означает, что любой стиль, который вы определяете в SFC, будет влиять только на элементы в том же файле. Даже дочерние компоненты не наследуют этот стиль по умолчанию.
Затем создайте файл AllPostsView.vue
с приведенным ниже кодом:
front_end/src/views/AllPostsView.vue
<script setup>
import PostList from "../components/PostList.vue";
</script>
<template>
<h2>Recent Posts</h2>
<PostList />
</template>
<style scoped>
h2 {
color: blue;
}
</style>
Точно так же, как в AuthorView.vue
, вы импортируете PostList
и отображаете его в своем HTML-блоке. На данный момент AllPostsView
выглядит так же, как AuthorView
, но позже вы измените его. Чтобы различать виды, вы можете изменить заголовок и его цвет.
Третий вид снова очень похож. Создайте PostsByTagView.vue
внутри папки views/
и добавьте приведенный ниже код:
front_end/src/views/PostsByTagView.vue
<script setup>
import PostList from "../components/PostList.vue";
</script>
<template>
<h2>Posts by Tag</h2>
<PostList />
</template>
<style scoped>
h2 {
color: green;
}
</style>
Последнее созданное вами представление называется PostView.vue
. Как следует из названия, это представление будет содержать одну запись вашего блога:
front_end/src/views/PostView.vue
<script setup>
import AuthorLink from "../components/AuthorLink.vue";
</script>
<template>
<h2>Post</h2>
<AuthorLink />
</template>
<style scoped>
h2 {
color: orange;
}
</style>
В этом представлении вы импортируете компонент AuthorLink
. Как и компоненты, которые вы импортировали в предыдущих представлениях, этот компонент еще не существует. Прежде чем вы создадите это, пришло время провести еще одну небольшую очистку.
Удалить существующие компоненты
Если вы перейдете к папке components/
внутри вашей папки src/
, то увидите, что там уже есть несколько файлов и папка icons/
. Продолжайте и удалите папку icons/
вместе с ее содержимым и этими тремя файлами:
WelcomeItem.vue
TheWelcome.vue
HelloWorld.vue
С чистой папкой components/
вы можете продолжить и создать компоненты, на которые вы ссылались в своих представлениях.
Создайте свои компоненты
В этом разделе вы создадите два компонента, которые вам понадобятся для вашего блога. Опять же, пока что вы оставите их базовыми и не будете добавлять к ним какой-либо специальный контент.
Начните с компонента, который позже отобразит ссылку на автора. Для этого создайте файл с именем AuthorLink.vue
в папке components/
:
front_end/src/components/AuthorLink.vue
<template>
<h3>Author Link</h3>
</template>
На данный момент это весь код, который вам нужен для проверки корректности отображения компонента. Позже вы добавите в него больше контента.
Далее создайте PostList.vue
в той же папке:
front_end/src/components/PostList.vue
<script setup>
import AuthorLink from "./AuthorLink.vue";
</script>
<template>
<h3>Posts List</h3>
<AuthorLink />
</template>
В PostList
также выполняется рендеринг AuthorLink
. Вы можете импортировать компоненты в качестве строительных блоков везде, где они вам нужны.
Настройка маршрутов
Если вы перейдете на страницу http://localhost:5173
прямо сейчас, вы все равно получите сообщение об ошибке. На данный момент сервер голосования по-прежнему ищет представления по умолчанию, созданные Vue в процессе создания каркасов.
Чтобы исправить неправильные маршруты и настроить маршруты для новых видов, откройте существующий файл index.js
в src/router/
. Замените содержимое на приведенный ниже код:
front_end/src/router/index.js
import { createRouter, createWebHistory } from "vue-router";
import AuthorView from "../views/AuthorView.vue";
import AllPostsView from "../views/AllPostsView.vue";
import PostView from "../views/PostView.vue";
import PostsByTagView from "../views/PostsByTagView.vue";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
name: "posts",
component: AllPostsView,
},
{
path: "/author",
name: "author",
component: AuthorView,
},
{
path: "/post",
name: "post",
component: PostView,
},
{
path: "/tag",
name: "tag",
component: PostsByTagView,
},
],
});
export default router;
Теперь, когда ваши маршруты указывают на существующие просмотры, все ошибки в выходных данных вашего видеосервера должны быть устранены. Для удобства перехода между различными страницами добавьте ссылки на маршруты в файл App.vue
.
Файл App.vue
является базовым компонентом, который ищет ваше приложение Vue. Вы можете найти его на видном месте непосредственно в папке src/
.
примечание: Если вы хотите, чтобы очистить ваш вю проект даже больше, то вы также можете удалить logo.svg
файл внутри src/assets/
папка на данный момент.
Откройте App.vue
и замените существующий контент на следующий:
front_end/src/App.vue
<script setup>
import { RouterLink, RouterView } from "vue-router";
</script>
<template>
<header>
<div class="wrapper">
<h1>My Blog 🐾</h1>
<nav>
<RouterLink to="/">Posts</RouterLink>
<RouterLink :to="{ name: 'author' }">Author</RouterLink>
<RouterLink :to="{ name: 'post' }">Post</RouterLink>
<RouterLink :to="{ name: 'tag' }">Tag</RouterLink>
</nav>
</div>
</header>
<RouterView />
</template>
<style scoped>
h1 {
text-align: center;
font-weight: bold;
margin-bottom: 1rem;
}
header {
border-bottom: 1px solid #ccc;
margin-bottom: 1rem;
}
nav {
text-align: center;
margin: 1rem 0;
}
nav a {
padding: 0.5rem;
}
</style>
Вы можете ссылаться на маршруты Vue либо по их пути, либо по названию. Позже вы снова удалите эти ссылки, потому что будете ссылаться на маршруты из своего контента. Но сейчас полезно добавить маршруты в навигацию, чтобы проверить, все ли работает.
Краткое описание шага 6
На этом шаге вы очистили часть папок проекта Vue и создали свои собственные представления и компоненты. Установив все маршруты, вы можете открыть http://localhost:5173
в своем браузере и посмотреть, как отображаются ваши компоненты.
Отлично! Теперь, когда вы убедились, что у вас есть доступ к просмотрам в браузере и что ваши компоненты отображаются корректно, вы можете продолжить и добавить в свои компоненты больше полезного контента.
Получите свой код: Нажмите здесь, чтобы загрузить бесплатный образец кода, который вы будете использовать для создания блога с использованием Django, GraphQL, и Vue.
Шаг 7: Обновите компоненты Vue
Ваши компоненты в конечном итоге будут отображать данные из конечной точки GraphQL. На данный момент вы просто заставите их отображать некоторый статический контент. С помощью приведенной ниже таблицы вы можете убедиться, что все ваши компоненты присутствуют:
Folder | Filename |
---|---|
src/ |
App.vue |
src/components/ |
AuthorLink.vue |
src/components/ |
PostList.vue |
src/views/ |
AllPostsView.vue |
src/views/ |
AuthorView.vue |
src/views/ |
PostView.vue |
src/views/ |
PostsByTagView.vue |
В следующих разделах вы сначала обновите свои более мелкие компоненты, а затем перейдете к компонентам представления. Вы будете вносить изменения в следующем порядке:
AuthorLink
: Укажите ссылку на страницу данного автора (используется вPost
иPostList
).PostList
: Отобразить заданный список записей в блоге (используется вAllPosts
,Author
, иPostsByTag
).AllPostsView
: Добавьте список всех записей.PostsByTagView:
Добавьте список записей, связанных с данным тегом.AuthorView:
Отображать информацию об авторе и список написанных им сообщений.PostView:
Отображение метаданных и содержимого для данной записи.App:
Удалите некоторые ссылки из навигации.
Вы пока не будете работать с динамическими данными из GraphQL API. Но, реализовав основную структуру каждого компонента, вы сможете сосредоточиться на функциональности GraphQL позже в руководстве.
Ссылка на автора
Компонент AuthorLink
должен принимать author
prop, структура которого соответствует данным об авторах в вашем GraphQL API. Реквизиты - это пользовательские атрибуты, которые вы можете использовать в своем компоненте. В компоненте должны быть указаны имя и фамилия автора, если они указаны, или имя пользователя автора в противном случае.
Замените существующее содержимое в файле AuthorLink.vue
на содержимое, приведенное ниже:
front_end/src/components/AuthorLink.vue
1<script setup>
2import { computed } from "vue";
3import { RouterLink } from "vue-router";
4
5const props = defineProps(["author"]);
6const firstName = props.author.user.firstName;
7const lastName = props.author.user.lastName;
8const displayName = computed(() => {
9 if (firstName && lastName) {
10 return `${firstName} ${lastName}`;
11 } else {
12 return `${props.author.user.username}`;
13 }
14});
15</script>
16
17<template>
18 <RouterLink
19 :to="{ name: 'author', params: { username: author.user.username } }"
20 >
21 {{ displayName }}
22 </RouterLink>
23</template>
Этот компонент будет работать не с GraphQL напрямую, а с переданным в author
объектом, который предоставляют другие компоненты. Чтобы иметь возможность работать с объектом author
, вы определяете его как prop в строке 5 с defineProps()
.
Функция defineProps()
возвращает объект, который вы можете сохранить в переменной. Это полезно, когда вы хотите получить доступ к свойствам из блока <script>
, как, например, в строках 6 и 7.
Примечание: Вы получаете доступ к реквизитам в вашем блоке <template>
напрямую, без добавления к ним префикса props
.
В строках с 18 по 22 вы создаете ссылку на страницу автора. Чтобы разрешить Vue создавать ссылки, вы работаете с компонентом RouterLink
. Отображаемое имя в строке 21 является значением вычисляемого свойства .
Вычисляемые свойства помогут вам внедрить сложные данные в ваш блок <template>
. Переменная displayName
, которую вы определяете в строке 8, будет либо именем и фамилией, либо именем пользователя автора.
Подготовьте список записей в блоге
Вы можете определить реквизиты компонента с помощью списка строк. Однако вы также можете уточнить информацию о предоставленных реквизитах, используя синтаксис объекта. Для компонента PostList
вы будете использовать объектный синтаксис для объявления более сложных реквизитов.
Компонент PostList
принимает posts
prop, структура которого соответствует данным о записях в вашем GraphQL API. Компонент также принимает логическое значение showAuthor
prop. В итоге компонент должен отображать следующие функции:
- Заголовок сообщения
- Ссылка на страницу сообщения
- Ссылка на автора публикации с помощью
AuthorLink
, еслиshowAuthor
естьtrue
Откройте PostList.vue
в каталоге src/components/
и обновите файл с выделенным содержимым, указанным ниже:
front_end/src/components/PostList.vue
1<script setup>
2import AuthorLink from "./AuthorLink.vue";
3import { RouterLink } from "vue-router";
4
5const props = defineProps({
6 posts: {
7 type: Array,
8 required: true,
9 },
10 showAuthor: {
11 type: Boolean,
12 required: false,
13 default: true,
14 },
15});
16</script>
17
18<template>
19 <ol class="post-list">
20 <li class="post" v-for="post in posts" :key="post.slug">
21 <RouterLink :to="{ name: 'post', params: { slug: post.slug } }">
22 {{ post.title }}
23 </RouterLink>
24 <span v-if="showAuthor"> by <AuthorLink :author="post.author" /> </span>
25 </li>
26 </ol>
27</template>
Более подробное описание реквизита, как в строке 5, может помочь вам и другим разработчикам лучше понять назначение предоставленного реквизита.
В этом компоненте вы получите список записей. Вы можете просмотреть их в строке 20. Когда вы используете v-for
встроенную директиву Vue для элемента, элемент и его содержимое отображаются на каждом шаге цикла.
На каждом шаге цикла вы показываете заголовок в виде ссылки, используя RouterLink
в строках с 21 по 23. Если для параметра showAuthor
задано значение true
, то в строке 24 также отображается компонент AuthorLink
.
Отрисовка всех записей в блоге
Теперь, когда вы отсортировали PostList
, вы можете перейти к обновлению AllPostsView
. Этот компонент должен отображать список всех записей в блоге.
Откройте компонент AllPosts.vue
в каталоге src/views/
и обновите его следующим содержимым:
front_end/src/views/AllPostsView.vue
1<script setup>
2import PostList from "../components/PostList.vue";
3
4const { result, loading, error } = {
5 error: { message: "No connection to the GraphQL API yet." },
6};
7</script>
8
9<template>
10 <h2>Recent Posts</h2>
11 <div v-if="loading">Loading...</div>
12 <div v-else-if="error" class="warn"></div>
13 <PostList v-else :posts="result.allPosts" />
14</template>
15
16<style scoped>
17 h2 {
18 color: blue;
19 }
20</style>
В строке 4 вы подготавливаете вызов GraphQL API, который вы реализуете позже. Вы деконструируете возвращаемый объект на result
, loading
, и error
, используя назначение деструкции JavaScript .
Пока вы извлекаете данные из API, loading
будет равно true
. Как только вы получите данные, это будет значение result
. Если что-то пойдет не так, то error
будет содержать свойство message
с дополнительной информацией.
На данный момент вы определяете только сообщение об ошибке в строке 5. Это означает, что вам не покажут Загрузка индикатор или PostList
компонента, потому что оба loading
и result
это undefined
на данный момент. Тем не менее, ваш блок <template>
идеально подготовлен для работы с данными, которые вы получите в result.allPosts
, когда позже реализуете вызов GraphQL API.
Показывать записи по заданному тегу
Затем обновите файл PostsByTagView.vue
в каталоге src/views/
, чтобы он соответствовал приведенному ниже коду:
front_end/src/views/PostsByTagView.vue
1<script setup>
2import PostList from "../components/PostList.vue";
3import { useRoute } from "vue-router";
4
5const route = useRoute();
6const tag = route.params.tag;
7const { result, loading, error } = {
8 error: { message: "No connection to the GraphQL API yet." },
9};
10</script>
11
12<template>
13 <div v-if="loading">Loading...</div>
14 <div v-else-if="error" class="warn">{{ error.message }}</div>
15 <section v-else :set="tagPosts = result.postsByTag">
16 <h2>Posts Tagged With "{{ tag }}"</h2>
17 <PostList v-if="tagPosts.length > 0" :posts="tagPosts" />
18 <p v-else>No posts found for this tag</p>
19 </section>
20</template>
21
22<style scoped>
23 h2 {
24 color: orange;
25 }
26</style>
Шаблон в строках с 7 по 9 такой же, как в AllPostsView
. Пока что вы будете работать с сообщением об ошибке с заполнителем и позже реализуете вызов GraphQL API.
Кроме того, вы вводите текущее имя тега для динамически согласованного маршрута в строке 6. Определение переменной tag
пригодится позже, когда вы будете фильтровать записи по этому конкретному тегу.
Чтобы упростить вам жизнь, вы определяете пользовательскую переменную для вашего шаблона в строке 15. Используя связанный атрибут для установки переменной tagPosts
, вы избавите себя от необходимости вводить текст позже. Таким образом, вы можете использовать tagPosts
в своем шаблоне вместо result.postsByTag
, которое вернет API.
Показать информацию об авторе
Компонент AuthorView
действует как страница профиля автора. На ней должна отображаться следующая информация:
- Заголовок с именем автора
- Подзаголовок с полным именем автора, если оно указано
- Ссылка на веб-сайт автора, если указана
- Биография автора, если указана
- Список записей автора, для которых
showAuthor
задано значениеfalse
Обновите файл AuthorView.vue
в src/views/
следующим образом:
front_end/src/views/AuthorView.vue
1<script setup>
2import PostList from "../components/PostList.vue";
3
4const { result, loading, error } = {
5 error: { message: "No connection to the GraphQL API yet." },
6};
7</script>
8
9<template>
10 <div v-if="loading">Loading...</div>
11 <div v-else-if="error">{{ error.message }}</div>
12 <section v-else :set="author = result.authorByUsername">
13 <h2>{{ author.user.username }}</h2>
14 <template v-if="author.user.firstName && author.user.lastName">
15 <h3>{{ author.user.firstName }} {{ author.user.lastName }}</h3>
16 </template>
17 <p v-if="author.bio">
18 {{ author.bio }}
19 <template v-if="author.website">
20 Learn more about {{ author.user.username }} on their
21 <a :href="author.website">website</a>.
22 </template>
23 </p>
24 <h3>Posts</h3>
25 <PostList
26 v-if="author.postSet"
27 :posts="author.postSet"
28 :showAuthor="false"
29 />
30 <p v-else>The author hasn't posted yet.</p>
31 </section>
32</template>
33
34<style scoped>
35 h2 {
36 color: red;
37 }
38</style>
Позже, когда вы получите данные из GraphQL API, вы отобразите информацию, указанную в строках с 13 по 30:
- В строке 13 в качестве заголовка указано имя пользователя автора.
- В строке 15 отображается полное имя автора, если заданы его имя и фамилия.
- Строка 17 проверяет, присутствует ли биография. Если это так, то вы отображаете биографию в строке 18 и добавляете необязательную ссылку на веб-сайт в строке 21.
- Строки с 25 по 29 отображают компонент
PostList
, если автор опубликовал сообщение. - Строка 30 показывает резервное сообщение, если в блоге нет записей.
После обновления AuthorView
осталось два компонента. Сначала вы перейдете к PostView
, а затем к App.vue
компоненту.
Отображение одной записи в блоге
Так же, как и модель данных Post
в вашем приложении Django, компонент PostView
немного сложнее, поскольку он отвечает за отображение всей информации о записи. Компонент должен отображать следующую информацию о записи:
- Заголовок и подзаголовок в качестве заголовка
- Автор в качестве ссылки с помощью
AuthorLink
- Дата публикации
- Мета-описание
- Основное содержание
- Список связанных тегов в виде ссылок
Обновите файл PostView.vue
в каталоге src/view/
, добавив выделенное содержимое ниже:
front_end/src/views/PostView.vue
1<script setup>
2import AuthorLink from "../components/AuthorLink.vue";
3
4const dateFormatter = new Intl.DateTimeFormat("en-US", { dateStyle: "full" });
5const displayableDate = (date) => dateFormatter.format(new Date(date));
6const { result, loading, error } = {
7 error: { message: "No connection to the GraphQL API yet." },
8};
9</script>
10
11<template>
12 <div v-if="loading">Loading...</div>
13 <div v-else-if="error" class="warn">{{ error.message }}</div>
14 <section v-else :set="post = result.postBySlug">
15 <h2>{{ post.title }}</h2>
16 <h3>{{ post.subtitle }}</h3>
17 <p>{{ post.metaDescription }}</p>
18 <aside>
19 Published on {{ displayableDate(post.publishDate) }}<br />
20 Written by <AuthorLink :author="post.author" />
21 <h4>Tags</h4>
22 <ul>
23 <li v-for="tag in post.tags" :key="tag.name">
24 <RouterLink :to="{ name: 'tag', params: { tag: tag.name } }">
25 {{ tag.name }}
26 </RouterLink>
27 </li>
28 </ul>
29 </aside>
30 <article>{{ post.body }}</article>
31 </section>
32</template>
33
34<!-- ... -->
Когда данные записи будут готовы, они будут сохранены в переменной result
, которую вы определяете в строке 6, и отобразят содержимое внутри блока <template>
в строках с 14 по 31.
В строке 19 вы передаете .publishDate
записи в displayableDate()
, которые вы определяете в строке 5. Дата публикации сохраняется в вашей базе данных как datetime
объект и без некоторой обработки будет выглядеть не очень хорошо. С помощью dateFormatter
в строке 4 вы возвращаете хорошо читаемую отформатированную дату в шаблоне.
В строках с 23 по 27 вы отображаете теги, содержащиеся в записи блога, в виде динамических ссылок. Каждая ссылка будет указывать на URL-адрес, соответствующий тегу. Пока что ваши маршруты не распознают дополнительный params
, подобный тому, который вы указали в строке 24. Так что это хорошее напоминание о том, что нужно заняться компонентом App
и следующими маршрутами.
Измените маршруты для приложения
На предыдущем шаге вы добавили несколько ссылок в навигацию вашего блога, чтобы проверить, отображаются ли представления и компоненты. При обновлении компонентов на этом шаге вы, возможно, заметили, что для большинства ваших ссылок требуются дополнительные параметры.
Единственный вид, для которого не требуются параметры, - это ваш AllPostsView
. Это единственная ссылка, которую вы хотите сохранить в своей навигации. Откройте App.vue
и удалите остальные ссылки:
front_end/src/App.vue
1<script setup>
2import { RouterLink, RouterView } from "vue-router";
3</script>
4
5<template>
6 <header>
7 <div class="wrapper">
8 <h1>My Blog 🐾</h1>
9 <nav>
10 <RouterLink to="/">Posts</RouterLink>
11 <!-- Remove the links to 'author', 'post', and 'tag' -->
12 </nav>
13 </div>
14 </header>
15
16 <RouterView />
17</template>
18
19<!-- ... -->
В строке 11 вы удаляете компоненты RouterLink
для author
, post
, и tag
. В будущем вы можете добавить страницу О или другие пункты меню в <nav>
. На данный момент сохраняйте основное меню, просто отображая Сообщений.
В вашем файле index.js
вы по-прежнему ссылаетесь на маршруты без каких-либо параметров. Обновите router/index.js
с параметрами маршрута, которые вы добавили в свои компоненты:
front_end/src/routes/index.js
1import { createRouter, createWebHistory } from "vue-router";
2import AuthorView from "../views/AuthorView.vue";
3import AllPostsView from "../views/AllPostsView.vue";
4import PostView from "../views/PostView.vue";
5import PostsByTagView from "../views/PostsByTagView.vue";
6
7const router = createRouter({
8 history: createWebHistory(import.meta.env.BASE_URL),
9 routes: [
10 {
11 path: "/",
12 name: "posts",
13 component: AllPostsView,
14 },
15 {
16 path: "/author/:username",
17 name: "author",
18 component: AuthorView,
19 },
20 {
21 path: "/post/:slug",
22 name: "post",
23 component: PostView,
24 },
25 {
26 path: "/tag/:tag",
27 name: "tag",
28 component: PostsByTagView,
29 },
30 ],
31});
32
33export default router;
В строках 16, 21 и 26 вы изменяете значения path
, чтобы они соответствовали параметрам маршрута, которые вы использовали при отображении компонентов RouterLink
. Не забудьте поставить двоеточие (:
) перед подстрокой параметра.
Краткое описание шага 7
Если вы раньше не часто пользовались Vue, этот шаг, возможно, дался вам нелегко. Тем не менее, вы достигли важного рубежа. У вас есть работающее приложение Vue с динамическими маршрутами и шаблонами, готовое к работе с контентом, который вскоре будет предоставлен GraphQL API.
Вы можете подтвердить, что ваше приложение работает, запустив сервер голосования и посетив http://localhost:5173
:
Вы должны увидеть ссылку Сообщений и заголовок Последних сообщений. Если вы это сделаете, то будете готовы к последнему шагу, на котором вы будете использовать Apollo для запроса вашего GraphQL API, чтобы объединить интерфейс и серверную часть.
Получите свой код: Нажмите здесь, чтобы загрузить бесплатный образец кода, который вы будете использовать для создания блога с использованием Django, GraphQL, и Vue.
Шаг 8: Внедрение Vue Apollo
Чтобы упростить выполнение запросов к GraphQL API, вы будете использовать клиент Vue Apollo. Для интеграции Vue Apollo в ваш проект вам необходимо установить пакеты Vue Apollo.
Установить Vue Apollo
Для удобной работы с Apollo в вашем проекте Vue вам понадобится клиент Vue Apollo и пакет apollo-composable
. Кроме того, вы установите GraphQL.js и graphql-tag
, которые помогут вам писать запросы GraphQL API.
Откройте окно терминала в папке front_end/
и установите пакеты с помощью этой команды:
$ npm install graphql graphql-tag @apollo/client @vue/apollo-composable
added 27 packages, and audited 50 packages in 6s
...
found 0 vulnerabilities
После установки всех пакетов вам необходимо внести некоторые коррективы, прежде чем вы сможете работать с запросами GraphQL в своих компонентах.
Настройка Vue Apollo
Vue Apollo в основном настраивается "из коробки", но вам нужно указать правильную конечную точку для запроса. Кроме того, вы хотите, чтобы клиент Apollo выполнял некоторое кэширование. Откройте main.js
в папке src/
и добавьте в файл конфигурацию вашего клиента Apollo:
front_end/src/main.js
import "./assets/main.css";
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import {
ApolloClient,
createHttpLink,
InMemoryCache,
} from "@apollo/client/core";
const httpLink = createHttpLink({
uri: "http://localhost:8000/graphql/",
});
const cache = new InMemoryCache();
const apolloClient = new ApolloClient({
link: httpLink,
cache,
});
const app = createApp(App);
app.use(router);
app.mount("#app");
Этими строками кода вы указываете клиенту Apollo, где найти GraphQL API. Кроме того, вы устанавливаете значение для кэша InMemoryCache()
. Это позволяет извлекать данные без лишних сетевых запросов, если данные не изменились.
Далее вам нужно запустить ваше приложение Vue с помощью клиента Apollo, используя компонуемый пакет Apollo. Оставайтесь в main.js
и обновите выделенные строки:
front_end/src/main.js
1import "./assets/main.css";
2
3import { createApp, provide, h } from "vue";
4import App from "./App.vue";
5import router from "./router";
6import {
7 ApolloClient,
8 createHttpLink,
9 InMemoryCache,
10} from "@apollo/client/core";
11import { DefaultApolloClient } from "@vue/apollo-composable";
12
13const httpLink = createHttpLink({
14 uri: "http://localhost:8000/graphql/",
15});
16
17const cache = new InMemoryCache();
18
19const apolloClient = new ApolloClient({
20 link: httpLink,
21 cache,
22});
23
24const app = createApp({
25 setup() {
26 provide(DefaultApolloClient, apolloClient);
27 },
28
29 render: () => h(App),
30});
31
32app.use(router);
33
34app.mount("#app");
Функция provide()
, которую вы импортируете в строке 3, позволяет компоненту предоставлять данные или методы всем своим компонентам-потомкам. Это особенно полезно для глубоко вложенных компонентов или когда вы хотите использовать общие функциональные возможности для многих компонентов. Прекрасным примером этого механизма является DefaultApolloClient
, который вы импортируете в строке 11. Переход от DefaultApolloClient
к provide()
в строке 26 делает клиент Apollo доступным во всех ваших компонентах.
В строке 3 вы также импортируете h()
. Vue использует функцию h()
render для создания виртуальных элементов DOM. Виртуальный DOM - это упрощенная копия объектной модели документа (DOM). В строке 29 вы указываете Vue использовать функцию h()
для создания виртуального DOM-представления компонента App
и монтирования его в качестве корневого каталога вашего приложения.
Краткое описание шага 8
На этом шаге вы установили дополнительные плагины, такие как Vue Apollo, и настроили клиент Apollo для работы с вашей серверной частью.
Когда вы проверяете свой интерфейс в браузере по адресу http://localhost:5173
, на поверхности ничего не меняется. Но это также означает, что ошибок нет и вы успешно настроили клиент Apollo.
Примечание: Если команда npm run dev
на данный момент не работает должным образом, вы можете попробовать переустановить свои пакеты с помощью npm install --include dev
.
Теперь ваше приложение Vue готово к работе с GraphQL API. Пришло время снова приступить к работе с серверной частью!
Получите свой код: Нажмите здесь, чтобы загрузить бесплатный образец кода, который вы будете использовать для создания блога с использованием Django, GraphQL, и Vue.
Шаг 9: Извлечение данных
Теперь, когда у вас все готово для отображения данных, когда они будут доступны, пришло время извлечь эти данные из вашего GraphQL API.
На этом последнем шаге руководства вы добавите запросы GraphQL для заполнения ваших страниц. Прежде чем продолжить, убедитесь, что ваш сервер разработки на Django запущен в отдельном окне терминала:
(venv) $ python manage.py runserver
На данный момент сервер Vita и сервер разработки Django должны быть запущены в двух отдельных окнах терминала.
Примечание: При обновлении компонентов на страницах вашего блога может появляться сообщение об ошибке “Не удалось загрузить”. Как только вы обновите все компоненты, эта ошибка должна исчезнуть.
Если вы не уверены в структуре запроса, то можете воспользоваться платформой GraphiQL по адресу http://localhost:8000/graphql
, чтобы протестировать свои запросы, прежде чем использовать их в своих компонентах.
AllPostsView
Запрос
Запрос для AllPostsView
должен возвращать только тот набор информации, который вы отображаете в своем шаблоне. Это означает, что вам нужны только заголовок вашего сообщения, фрагмент и информация об авторе:
src/views/AllPostsView.vue
1<script setup>
2import PostList from "../components/PostList.vue";
3import { useQuery } from "@vue/apollo-composable";
4import gql from "graphql-tag";
5
6const { result, loading, error } = useQuery(gql`
7 query {
8 allPosts {
9 title
10 slug
11 author {
12 user {
13 username
14 firstName
15 lastName
16 }
17 }
18 }
19 }
20`);
21</script>
22
23<!-- ... -->
В строке 3 вы импортируете useQuery()
, что позволяет вам выполнить запрос и оперативно отслеживать его результат. gql
, который вы импортируете в строке 4, поможет вам преобразовать строку запроса GraphQL в документ запроса, который useQuery()
может быть понятен и с которым можно работать.
Вы определяете запрос GraphQL в строках с 7 по 19 в шаблонном литерале gql
. Содержимое - это та же строка, которую вы использовали бы на платформе GraphiQL. Здесь вы запрашиваете только тот конкретный набор данных, который вам нужен в вашем шаблоне.
Когда вы вызываете useQuery()
с помощью запроса GraphQL, он возвращает объект, содержащий три свойства:
result
, который будет заполнен результатом вашего запроса, как только он будет успешно завершенloading
, который равенtrue
во время выполнения запросаerror
, который будет содержать подробную информацию, если возникнет проблема с запросом API
Эти три свойства позволяют вам управлять отображением определенной информации для пользователя. Вы уже подготовили свой шаблон для работы со свойствами, поэтому можете сохранить содержимое в <template>
как есть и перейти к следующему компоненту.
PostView
Запрос
Запрос для отдельной записи должен содержать slug
для нужной записи. Он должен возвращать всю необходимую информацию для отображения информации о публикации и ее содержании. Следовательно, код, обеспечивающий выполнение запроса, немного сложнее.
Обновите свой компонент PostView
с помощью выделенного ниже кода:
src/views/PostView.vue
1<script setup>
2import AuthorLink from "../components/AuthorLink.vue";
3import { useRoute } from "vue-router";
4import { useQuery } from "@vue/apollo-composable";
5import gql from "graphql-tag";
6
7const dateFormatter = new Intl.DateTimeFormat("en-US", { dateStyle: "full" });
8const displayableDate = (date) => dateFormatter.format(new Date(date));
9const route = useRoute();
10const slug = route.params.slug;
11const { result, loading, error } = useQuery(gql`
12 query {
13 postBySlug(
14 slug: "${slug}"
15 ) {
16 title
17 subtitle
18 publishDate
19 published
20 metaDescription
21 slug
22 body
23 author {
24 user {
25 username
26 firstName
27 lastName
28 }
29 }
30 tags {
31 name
32 }
33 }
34 }
35`);
36</script>
37
38<!-- ... -->
Этот запрос запрашивает большую часть данных о публикации и связанных с ней авторах и тегах. На этот раз вам потребуется проделать небольшую дополнительную работу.
В строках 9 и 10 вы определяете route
и извлекаете slug из параметров вашего маршрута. Затем вы используете slug для своего запроса в строке 14.
AuthorView
Запрос
В запросе для PostView
вы извлекли данные отдельного поста и некоторые вложенные данные об авторе. В запросе AuthorView
вам нужно будет получить данные об авторе и список всех публикаций автора.
Запрос author принимает username
желаемого автора и должен возвращать всю необходимую информацию для отображения автора и списка его публикаций. Это должно выглядеть следующим образом:
src/views/AuthorView.vue
<script setup>
import PostList from "../components/PostList.vue";
import { useRoute } from "vue-router";
import { useQuery } from "@vue/apollo-composable";
import gql from "graphql-tag";
const route = useRoute();
const username = route.params.username;
const { result, loading, error } = useQuery(gql`
query {
authorByUsername(
username: "${username}"
) {
website
bio
user {
firstName
lastName
username
}
postSet {
title
slug
}
}
}
`);
</script>
<!-- ... -->
В этом запросе используется postSet
, что может показаться знакомым, если вы ранее занимались моделированием данных в Django. Название “post set” происходит от обратной связи, которую Django создает для поля ForeignKey
. В этом случае запись имеет отношение внешнего ключа к ее автору, которое имеет обратную связь с записью с именем post_set
. Graphene-Django автоматически отображает это как postSet
в GraphQL API.
PostsByTagView
Запрос
Запрос для PostsByTagView
очень похож на запрос в AllPostsView
. Важное отличие заключается в том, что запрос в PostsByTagView
требует желаемого tag
и возвращает список совпадающих записей.
Откройте PostsByTagView.vue
и измените файл с помощью выделенного ниже кода:
src/views/PostsByTagView.vue
<script setup>
import PostList from "../components/PostList.vue";
import { useRoute } from "vue-router";
import { useQuery } from "@vue/apollo-composable";
import gql from "graphql-tag";
const route = useRoute();
const tag = route.params.tag;
const { result, loading, error } = useQuery(gql`
query {
postsByTag(
tag: "${tag}"
) {
title
slug
author {
user {
username
firstName
lastName
}
}
}
}
`);
</script>
<!-- ... -->
Вы можете заметить, что некоторые фрагменты каждого запроса выглядят очень похожими друг на друга. Хотя это и не будет рассмотрено в данном руководстве, вы можете использовать фрагменты GraphQL, чтобы уменьшить дублирование кода запроса.
Краткое описание шага 9
Теперь, когда каждый компонент извлекает данные, необходимые для отображения, вы получили работающий блог. Запустите сервер разработки Django и сервер разработки Vue. Посетите http://localhost:5173
и просмотрите свой блог.
Поздравляем! Вы начали с создания серверной части блога Django для администрирования, сохранения и предоставления данных для блога. Затем вы создали интерфейс Vue для использования и отображения этих данных. Вы заставили их взаимодействовать с GraphQL с помощью Graphene и Apollo. Отличная работа!
Следующие шаги
Возможно, вы уже задаетесь вопросом, что делать дальше. Чтобы убедиться, что ваш блог работает должным образом, вы можете попробовать следующее:
- Добавьте дополнительные страницы, например страницу О , в меню навигации вашего блога.
- Создайте обзорные страницы, на которых будут отображаться все авторы и теги.
- Сделайте некоторые записи неопубликованными, чтобы убедиться, что они не отображаются в блоге.
Если вы чувствуете уверенность в себе и готовы к приключениям в том, что у вас происходит, вы также можете развить свою систему еще больше:
- Расширьте свою модель данных, чтобы создать новое поведение в своем блоге на Django.
- Создавайте новые запросы, чтобы получить интересные представления о данных вашего блога.
- Изучите мутации в GraphQL, чтобы записывать данные в дополнение к их чтению.
- Добавьте CSS в свои однофайловые компоненты, чтобы сделать блог более привлекательным.
Моделирование данных и архитектура компонентов, которые вы создали, удивительно расширяемы, так что пользуйтесь ими сколько хотите!
Заключение
Вы уже видели, как можно использовать GraphQL для создания типизированных, гибких представлений ваших данных. Вы можете использовать эти же методы в существующем приложении Django, которое вы уже создали или планируете создать в будущем. Как и другие API-интерфейсы, вы также можете использовать свой практически в любом клиентском фреймворке.
В этом руководстве вы узнали, как:
- Создайте блог Django модель данных и интерфейс администратора
- Оберните вашу модель данных в GraphQL API используя Graphene-Django
- Создание и маршрутизация отдельных компонентов Vue для каждого представления данных
- Запросите API GraphQL динамически для заполнения ваших компонентов Vue с помощью Apollo
Вы прошли большой путь, поэтому постарайтесь найти новые способы использования этих понятий в различных контекстах, чтобы закрепить полученные знания. Удачного программирования и удачного ведения блога!
Вы можете загрузить полный исходный код для этого проекта, перейдя по ссылке ниже:
Получите свой код: Нажмите здесь, чтобы загрузить бесплатный образец кода, который вы будете использовать для создания блога с использованием Django, GraphQL, и Vue.
Вернуться на верх