iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0

排序

在新增資料排序的功能之前,先新增一個 Python 檔:

$ touch server/app/blog/graph/orders.py

接著編輯server/app/blog/graph/orders.py

import strawberry
import strawberry_django

from server.app.blog import models as blog_models

@strawberry_django.order(blog_models.Post)
class PostOrder:
    published_at: strawberry.auto

@strawberry_django.order(blog_models.Tag)
class TagOrder:
    name: strawberry.auto

然後有兩種方式可以設定排序:

一種是加在型態上面,讓所有有用到那個型態的地方都可以對該型態的資料排序,下面用標籤來做示範,編輯server/app/blog/graph/types.py

# ... 省略
from server.app.blog import models as blog_models
+from server.app.blog.graph import orders as blog_orders
# ... 省略
-@strawberry_django.type(blog_models.Tag)
+@strawberry_django.type(blog_models.Tag, order=blog_orders.TagOrder)
class Tag:
    name: str

https://ithelp.ithome.com.tw/upload/images/20231002/20161957AY1DGA8z9R.png

上面的查詢可以看到,文章的查詢裡面可以在文章的標籤欄位做排序。

另一種設定排序的方式加在欄位上面,就是只在有需要用到排序的地方使用,下面在server/app/blog/graph/queries.py進行編輯:

# ... 省略
+from server.app.blog.graph import orders as blog_orders
from server.app.blog.graph import types as blog_types
# ... 省略
@strawberry.type
class Query:
-		posts: list[blog_types.Post] = strawberry_django.field()
+   posts: list[blog_types.Post] = strawberry_django.field(order=blog_orders.PostOrder)
		# ... 省略

https://ithelp.ithome.com.tw/upload/images/20231002/201619578BJ3IkE2fg.png

上面的查詢可以看到,可以對文章的發布時間做排序,然後因為標籤是在型態上加上排序功能,所以在標籤的查詢上也可以做資料排序。

由於 strawberry_django 還是一個發展中的套件,目前排序功能上還有許多問題與缺少的功能:

  • 無法自定義排序函式:https://github.com/strawberry-graphql/strawberry-graphql-django/issues/236
  • 多個排序欄位的順序:https://github.com/strawberry-graphql/strawberry-graphql-django/issues/150

分頁

在 strawberry_django 中加上分頁功能是很簡單的,只需要在欄位或是型態上設定pagination=True就可以了,下面以文章的查詢為例:

# ... 省略
@strawberry.type
class Query:
-   posts: list[blog_types.Post] = strawberry_django.field(order=blog_orders.PostOrder)
+		posts: list[blog_types.Post] = strawberry_django.field(
+       order=blog_orders.PostOrder,
+       pagination=True,
+   )
		# ... 省略

https://ithelp.ithome.com.tw/upload/images/20231002/20161957nJUw8pJE42.png

strawberry_django 提供的分頁功能的風格是基於位移的分頁(Offset-Based Pagination):

  • limit:一次可以回傳資料筆數。
  • offset:位移,從 0 開始。

由於 strawberry_django 還是一個發展中的套件,目前分頁功能上還有許多問題與缺少的功能:

  • 自定義分頁需要自行處理:https://github.com/strawberry-graphql/strawberry-graphql-django/issues/89
  • 基於位移的分頁 limit 沒有預設最大值:https://github.com/strawberry-graphql/strawberry-graphql-django/issues/308

增加使用者型態

最後把缺少的User型態補上,首先建立一個新的應用程式:

$ cd django-graphql-tutorial/server/app
$ django-admin startapp authentication

接著設定應用程式名稱,並註冊應用程式到 Django:

# server/app/authentication/apps.py
from django.apps import AppConfig

class AuthenticationConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
+   name = "server.app.authentication"
# server/settings.py
# ... 省略
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django_extensions",
    "server.app.blog",
+   "server.app.authentication",
]
# ... 省略

接下來在authentication內增加graph模組:

$ mkdir -p server/app/authentication/graph
$ touch server/app/authentication/graph/__init__.py
$ touch server/app/authentication/graph/types.py

server/app/authentication/graph/types.py中新增以下程式碼:

import strawberry_django
from django.contrib.auth import get_user_model

__all__ = ("User",)

USER_MODEL = get_user_model()

@strawberry_django.type(USER_MODEL)
class User:
    username: str
    first_name: str
    last_name: str
    email: str

最後將原本部落格應用程式裡的author_id改成author

# server/app/blog/graph/types.py
# ... 省略
+from server.app.authentication.graph import types as auth_types
from server.app.blog import models as blog_models
from server.app.blog.graph import orders as blog_orders
# ... 省略
@strawberry_django.type(blog_models.Post)
class Post:
    id: uuid.UUID  # noqa: A003
    slug: str
-		author_id: strawberry.ID
+   author: auth_types.User
		# ... 省略

# ... 省略

@strawberry_django.type(blog_models.Comment)
class Comment:
    id: uuid.UUID  # noqa: A003
    post: Post
    parent: typing.Optional["Comment"]
-    author_id: strawberry.ID | None
+   author: auth_types.User | None
    content: str

https://ithelp.ithome.com.tw/upload/images/20231002/20161957tpWKGUpdbR.png

這次修改內容可以參考 Git commit:https://github.com/JiaWeiXie/django-graphql-tutorial/commit/0391081075600ac3a18362088a815772f1e6fa0a

參考資料


上一篇
Day 16:Strawberry Django 客製化查詢與 Resolvers
下一篇
Day 18:Strawberry Django 資料篩選
系列文
Django 與 Strawberry GraphQL:探索現代 API 開發之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言