Recursive complex filtering #181
Some checks failed
Test before pr merge / test-lint (pull_request) Failing after 6s
Some checks failed
Test before pr merge / test-lint (pull_request) Failing after 6s
This commit is contained in:
@@ -14,6 +14,8 @@ from cpl.core.utils.cache import Cache
|
||||
from cpl.database.mysql.mysql_module import MySQLModule
|
||||
from cpl.graphql.application.graphql_app import GraphQLApp
|
||||
from cpl.graphql.graphql_module import GraphQLModule
|
||||
from model.author_dao import AuthorDao
|
||||
from model.author_query import AuthorGraphType, AuthorFilter, AuthorSort
|
||||
from model.post_dao import PostDao
|
||||
from model.post_query import PostFilter, PostSort, PostGraphType
|
||||
from queries.hello import HelloQuery
|
||||
@@ -49,14 +51,18 @@ def main():
|
||||
.add_transient(AuthUserFilter)
|
||||
.add_transient(AuthUserSort)
|
||||
.add_transient(HelloQuery)
|
||||
# test data
|
||||
.add_singleton(TestDataSeeder)
|
||||
# authors
|
||||
.add_transient(AuthorDao)
|
||||
.add_transient(AuthorGraphType)
|
||||
.add_transient(AuthorFilter)
|
||||
.add_transient(AuthorSort)
|
||||
# posts
|
||||
.add_transient(PostDao)
|
||||
.add_transient(PostGraphType)
|
||||
.add_transient(PostFilter)
|
||||
.add_transient(PostSort)
|
||||
|
||||
# test data
|
||||
.add_singleton(TestDataSeeder)
|
||||
)
|
||||
|
||||
app = builder.build()
|
||||
@@ -78,6 +84,7 @@ def main():
|
||||
schema = app.with_graphql()
|
||||
schema.query.string_field("ping", resolver=lambda: "pong")
|
||||
schema.query.with_query("hello", HelloQuery)
|
||||
schema.query.dao_collection_field(AuthorGraphType, AuthorDao, "authors", AuthorFilter, AuthorSort)
|
||||
schema.query.dao_collection_field(PostGraphType, PostDao, "posts", PostFilter, PostSort)
|
||||
|
||||
app.with_playground()
|
||||
|
||||
30
example/api/src/model/author.py
Normal file
30
example/api/src/model/author.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from datetime import datetime
|
||||
from typing import Self
|
||||
|
||||
from cpl.core.typing import SerialId
|
||||
from cpl.database.abc import DbModelABC
|
||||
|
||||
|
||||
class Author(DbModelABC[Self]):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: int,
|
||||
first_name: str,
|
||||
last_name: str,
|
||||
deleted: bool = False,
|
||||
editor_id: SerialId | None = None,
|
||||
created: datetime | None = None,
|
||||
updated: datetime | None = None,
|
||||
):
|
||||
DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
|
||||
self._first_name = first_name
|
||||
self._last_name = last_name
|
||||
|
||||
@property
|
||||
def first_name(self) -> str:
|
||||
return self._first_name
|
||||
|
||||
@property
|
||||
def last_name(self) -> str:
|
||||
return self._last_name
|
||||
11
example/api/src/model/author_dao.py
Normal file
11
example/api/src/model/author_dao.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from cpl.database.abc import DbModelDaoABC
|
||||
from model.author import Author
|
||||
|
||||
|
||||
class AuthorDao(DbModelDaoABC):
|
||||
|
||||
def __init__(self):
|
||||
DbModelDaoABC.__init__(self, Author, "authors")
|
||||
|
||||
self.attribute(Author.first_name, str)
|
||||
self.attribute(Author.last_name, str)
|
||||
37
example/api/src/model/author_query.py
Normal file
37
example/api/src/model/author_query.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from cpl.graphql.schema.filter.filter import Filter
|
||||
from cpl.graphql.schema.graph_type import GraphType
|
||||
from cpl.graphql.schema.sort.sort import Sort
|
||||
from cpl.graphql.schema.sort.sort_order import SortOrder
|
||||
from model.author import Author
|
||||
|
||||
class AuthorFilter(Filter[Author]):
|
||||
def __init__(self):
|
||||
Filter.__init__(self)
|
||||
self.int_field("id")
|
||||
self.string_field("firstName")
|
||||
self.string_field("lastName")
|
||||
|
||||
class AuthorSort(Sort[Author]):
|
||||
def __init__(self):
|
||||
Sort.__init__(self)
|
||||
self.field("id", SortOrder)
|
||||
self.field("firstName", SortOrder)
|
||||
self.field("lastName", SortOrder)
|
||||
|
||||
class AuthorGraphType(GraphType[Author]):
|
||||
|
||||
def __init__(self):
|
||||
GraphType.__init__(self)
|
||||
|
||||
self.int_field(
|
||||
"id",
|
||||
resolver=lambda root: root.id,
|
||||
)
|
||||
self.string_field(
|
||||
"firstName",
|
||||
resolver=lambda root: root.first_name,
|
||||
)
|
||||
self.string_field(
|
||||
"lastName",
|
||||
resolver=lambda root: root.last_name,
|
||||
)
|
||||
@@ -10,6 +10,7 @@ class Post(DbModelABC[Self]):
|
||||
def __init__(
|
||||
self,
|
||||
id: int,
|
||||
author_id: SerialId,
|
||||
title: str,
|
||||
content: str,
|
||||
deleted: bool = False,
|
||||
@@ -18,9 +19,14 @@ class Post(DbModelABC[Self]):
|
||||
updated: datetime | None = None,
|
||||
):
|
||||
DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
|
||||
self._author_id = author_id
|
||||
self._title = title
|
||||
self._content = content
|
||||
|
||||
@property
|
||||
def author_id(self) -> SerialId:
|
||||
return self._author_id
|
||||
|
||||
@property
|
||||
def title(self) -> str:
|
||||
return self._title
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
from cpl.database.abc import DbModelDaoABC
|
||||
from model.author_dao import AuthorDao
|
||||
from model.post import Post
|
||||
|
||||
|
||||
class PostDao(DbModelDaoABC):
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, authors: AuthorDao):
|
||||
DbModelDaoABC.__init__(self, Post, "posts")
|
||||
|
||||
self.attribute(Post.author_id, int, db_name="authorId")
|
||||
self.reference("author", "id", Post.author_id, "authors", authors)
|
||||
|
||||
self.attribute(Post.title, str)
|
||||
self.attribute(Post.content, str)
|
||||
@@ -2,12 +2,15 @@ from cpl.graphql.schema.filter.filter import Filter
|
||||
from cpl.graphql.schema.graph_type import GraphType
|
||||
from cpl.graphql.schema.sort.sort import Sort
|
||||
from cpl.graphql.schema.sort.sort_order import SortOrder
|
||||
from model.author_dao import AuthorDao
|
||||
from model.author_query import AuthorGraphType, AuthorFilter
|
||||
from model.post import Post
|
||||
|
||||
class PostFilter(Filter[Post]):
|
||||
def __init__(self):
|
||||
Filter.__init__(self)
|
||||
self.int_field("id")
|
||||
self.filter_field("author", AuthorFilter)
|
||||
self.string_field("title")
|
||||
self.string_field("content")
|
||||
|
||||
@@ -20,13 +23,22 @@ class PostSort(Sort[Post]):
|
||||
|
||||
class PostGraphType(GraphType[Post]):
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, authors: AuthorDao):
|
||||
GraphType.__init__(self)
|
||||
|
||||
self.int_field(
|
||||
"id",
|
||||
resolver=lambda root: root.id,
|
||||
)
|
||||
|
||||
async def _a(root: Post):
|
||||
return await authors.get_by_id(root.author_id)
|
||||
|
||||
self.object_field(
|
||||
"author",
|
||||
AuthorGraphType,
|
||||
resolver=_a#lambda root: root.author_id,
|
||||
)
|
||||
self.string_field(
|
||||
"title",
|
||||
resolver=lambda root: root.title,
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
CREATE TABLE IF NOT EXISTS `authors` (
|
||||
`id` INT(30) NOT NULL AUTO_INCREMENT,
|
||||
`firstname` VARCHAR(64) NOT NULL,
|
||||
`lastname` VARCHAR(64) NOT NULL,
|
||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
editorId INT NULL,
|
||||
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY(`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `posts` (
|
||||
`id` INT(30) NOT NULL AUTO_INCREMENT,
|
||||
`title` VARCHAR(64) NOT NULL,
|
||||
`content` VARCHAR(512) NOT NULL,
|
||||
`authorId` INT(30) NOT NULL REFERENCES `authors`(`id`) ON DELETE CASCADE,
|
||||
`title` TEXT NOT NULL,
|
||||
`content` TEXT NOT NULL,
|
||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
editorId INT NULL,
|
||||
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
@@ -2,6 +2,8 @@ from faker import Faker
|
||||
|
||||
from cpl.database.abc import DataSeederABC
|
||||
from cpl.query import Enumerable
|
||||
from model.author import Author
|
||||
from model.author_dao import AuthorDao
|
||||
from model.post import Post
|
||||
from model.post_dao import PostDao
|
||||
|
||||
@@ -11,19 +13,34 @@ fake = Faker()
|
||||
|
||||
class TestDataSeeder(DataSeederABC):
|
||||
|
||||
def __init__(self, posts: PostDao):
|
||||
def __init__(self, authors: AuthorDao, posts: PostDao):
|
||||
DataSeederABC.__init__(self)
|
||||
|
||||
self._authors = authors
|
||||
self._posts = posts
|
||||
|
||||
async def seed(self):
|
||||
if await self._authors.count() == 0:
|
||||
await self._seed_authors()
|
||||
|
||||
if await self._posts.count() == 0:
|
||||
await self._seed_posts()
|
||||
|
||||
async def _seed_authors(self):
|
||||
authors = Enumerable.range(0, 35).select(
|
||||
lambda x: Author(
|
||||
0,
|
||||
fake.first_name(),
|
||||
fake.last_name(),
|
||||
)
|
||||
).to_list()
|
||||
await self._authors.create_many(authors, skip_editor=True)
|
||||
|
||||
async def _seed_posts(self):
|
||||
posts = Enumerable.range(0, 100).select(
|
||||
lambda x: Post(
|
||||
id=0,
|
||||
author_id=fake.random_int(min=1, max=35),
|
||||
title=fake.sentence(nb_words=6),
|
||||
content=fake.paragraph(nb_sentences=6),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user