You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
*`@api` decorator added `timeout` parameter to specifiy the timeout for API function processing time or Client request timeout.
12
+
* Added HTTP cache plugin: `api.Cache`: can handle HTTP caching like `Last-Modifed` / `Etag` automatically
13
+
* Added search parameter `orm.Search`, support various search mode for multiple model fields: [Search Param](../../guide/schema-query/#search-param)
14
+
*`orm.Schema` support defining request context variables (such as current request user / IP) and query request context fields by passing the current request object to `context` param of the serialize methods: [Use context vars in query function](../../guide/schema-query/#relational-query-function)
15
+
*`meta gen_openapi` support `--split` parameter that spliting the API document in seperate files by endpoint, convenient for AI tools to parse and read
16
+
17
+
### Optimized
18
+
19
+
* Optimize `orm.Field` field parsing and rule merging.
20
+
* Client reuse request session (`httpx.Client` / `aiohttp.Session` / `requests.Session`) in `with` and `async with` block.
21
+
22
+
### Fixed
23
+
24
+
* Fix YAML output format of generated OpenAPI document.
Copy file name to clipboardExpand all lines: docs/en/guide/schema-query.md
+84-69Lines changed: 84 additions & 69 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -401,35 +401,8 @@ The pre-condition for `queryset` parameter is to specify a **Multiple Relation N
401
401
!!! warning "No Slicing"
402
402
Please **DO NOT** slice the specified `queryset` (such as limiting the number of returned results), because in order to optimize N+1 query problems, The query implementation of `queryset` is to query all relational objects at once and distribute them according to their corresponding relationships. If you slice the queryset, the list of relational objects assigned to the queried instances may be incomplete. If you need to implement a requirement similar to "querying up to N relational objects per instance", please refer to the **relational query function** below.
403
403
404
-
### Relational query function
405
-
406
-
Relational query function provides a hook that can be customized. You can write any condition for the relational query, such as adding filter and sort conditions, controlling the quantity, etc. The relational query function can be declared in the following ways
407
-
408
-
#### Single primary-key function
409
-
The function accepts a single primary key of the target queryset as input, and returns the related queryset. Let’s take a requirement as an example: we need to query a list of users, each user needs to attach **two most liked articles**. The code example for implementation is as follows
410
-
411
-
```python hl_lines="8-12"
412
-
classArticleSchema(orm.Schema[Article]):
413
-
id: int
414
-
content: str
415
-
416
-
classUserSchema(orm.Schema[User]):
417
-
username: str
418
-
top_2_articles: List[ArticleSchema] = orm.Field(
419
-
lambdauser_id: Article.objects.annotate(
420
-
favorites_num=models.Count('favorited_bys')
421
-
).filter(
422
-
author_id=user_id
423
-
).order_by('-favorites_num')[:2]
424
-
)
425
-
```
426
-
427
-
In this example, the `top_2_articles` field of UserSchema specifies a relational query function, which accepts a primary key value of the target user and returns the corresponding article queryset. UtilMeta will complete the serialization and result distribution according to the type annotation ( `List[ArticleSchema]`) of the field
428
-
429
-
**Optimized compression of a single relationship object**
430
-
431
-
Looking at the above example, we can clearly see that in order to get the conditional relation value of the target, the query in the function needs to run N times, N is the length of the target queryset, so what can be compressed into a single query?
432
-
The answer is that when you only need to query **1** of the target relational object, you can directly declare the queryset, and UtilMeta will process it into a **subquery** to compress it into a single query, such as
404
+
#### Single relationship object
405
+
when you only need to query **1** of the target relational object, you can directly declare the queryset, and UtilMeta will process it into a **subquery** to compress it into a single query, such as
433
406
434
407
```python hl_lines="8-12"
435
408
classArticleSchema(orm.Schema[Article]):
@@ -449,37 +422,44 @@ class UserSchema(orm.Schema[User]):
449
422
450
423
!!! tip "OuterRef"
451
424
Django uses `OuterRef` to reference the outer fields, in the example, we referenced the primary key of the target User model
425
+
### Relational query function
426
+
427
+
Relational query function provides a hook that can be customized. You can write any condition for the relational query, such as adding filter and sort conditions, controlling the quantity, etc. The relational query function can be declared in the following ways
428
+
429
+
Let’s take a requirement as an example. Suppose we need to query a list of users, in which each user needs to attach “**Followers the current request user knows**”, which is a common requirement in social media such as Twitter (X). so the requirement can be simply and efficiently implemented by using the primary key list function.
452
430
453
-
#### Primary-Key List Function
454
-
Let’s take another requirement as an example. Suppose we need to query a list of users, in which each user needs to attach “**Followers the current request user knows**”, which is a common requirement in social media such as Twitter (X). so the requirement can be simply and efficiently implemented by using the primary key list function.
In the example, `UserSchema` defines a class function that generate different queries for different requesting users, in which we define a `get_followers_you_known` query function that accepts a list of **queried primary keys** of current Schema instances and constructs a dict that map each key with a primary key list of the **target relationship** (Followers you known). After this dictionary is returned, UtilMeta will complete the subsequent aggregate query and result distribution. Finally, the followers_you_known field of each user Schema instance will contain the query results that meet the condition requirement
478
454
479
-
!!! tip "Dynamic Schema Query"
480
-
For the above example, you can call `UserSchema.get_runtime_schema(request_user_id)` in the API function to get the dynamic generated Schema class based on the user id of the current request, we often call it **Dynamic Schema Query**
481
-
482
-
455
+
!!! tip
456
+
Query function can use properties of `request.var` as the request context variables, such as:
457
+
`request.var.user_id`:Current request user ID,
458
+
`request.var.user`: Current request user instance,
459
+
`request.var.ip`: Current request IP address.
460
+
461
+
You can pass the current request object (`self.request` of API) as the `context` param of the `init` / `serialize` method, such as `UserSchema.init(1, context=self.request)` to query the context fields
462
+
483
463
### Value query function
484
464
485
465
Above, we introduced the relational query function, which needs to correspond the primary key of the currently queried data with the primary key of the related model for the target field, and then serialize it using the relational model schema defined by the field.
@@ -555,45 +535,45 @@ Here are some expressions that are commonly used in real-world development
555
535
#### `Exists`
556
536
Sometimes you need to return the field of whether a conditional queryset exists, for example, when querying a user, you can use `Exists` an expression to return "**whether the current request user has followed**".
For some relation counts you may need to add some conditions, for example, when querying an article, you need to return "**how many of the current user’s followings liked the article**", in which case you can use `SubqueryCount` expressions.
579
558
580
559
```python hl_lines="10"
560
+
from utilmeta.core import orm, request
581
561
from utilmeta.core.orm.backends.django import expressions as exp
@@ -794,6 +774,41 @@ In addition, you can specify a query expression with the `query` parameter of `
794
774
*`default`: Specify default values for query parameter
795
775
*`alias`: Specify an alias for the query parameter
796
776
777
+
#### Search Param
778
+
779
+
A commonly used type of query parameter is used to search for fuzzy matching of one or more fields of the target. Such search parameter can be defined using the `orm.Search` in UtilMeta, such as
`orm.Search` can receive strings or a field references of model that can be used for searching (usually text strings containing the main information of the model, such as title, summary, description, etc.), in addition, there are some search settings that can be specified:
800
+
801
+
*`case_sensitive`: Whether to search case sensitively, default to False
802
+
*`keyword_delimiters`: Specify the delimiter for keywords. the search text will be divided into keywords first, and then the fields will be queried and matched. The default is `(' ', ',', ';', '|')`
803
+
*`match_mode`: Match mode for field and keywords, includes:
804
+
* `orm.Search.ANY_ANY`: Match any field with any keyword for the most relaxed search
805
+
* `orm.Search.UNION_ALL`: The searchable fields of the instance can match all keywords (which can be divided into any one or more fields)
806
+
* `orm.Search.ANY_ALL`: Any single searchable field needs to match all keywords, **default**
807
+
* `orm.Search.ALL_ALL`: All fields need to match all keywords, the strictest search
808
+
809
+
!!! note
810
+
UtilMeta >= 2.8.0 支持 `orm.Search` 搜索参数
811
+
797
812
### Sorting params
798
813
799
814
You can also declare sorting parameter in `orm.Query` class. with the supported sorting fields and the corresponding configuration. Examples are as follows
0 commit comments