Skip to content

Commit 7698ce3

Browse files
committed
update changelog, minor fixes, add examples
1 parent 188093e commit 7698ce3

File tree

10 files changed

+197
-78
lines changed

10 files changed

+197
-78
lines changed

.github/workflows/testing.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
python -m pip install --upgrade pip poetry pre-commit
2525
poetry config virtualenvs.create false --local
2626
- name: Install dependencies
27-
run: poetry install
27+
run: poetry install --extras "sqla"
2828
- name: Lint code
2929
run: pre-commit run --all-files
3030
- name: Test with pytest

docs/changelog.rst

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,38 @@
11
Changelog
2-
*********
2+
#########
3+
34

45
**0.4.0**
5-
=========
6+
*********
67

78
Backward-incompatible changes, improvements, bug fixes
89
======================================================
910

10-
* Includes (see doc TODO link)
11+
* Includes (see :ref:`example with many-to-many <include_many_to_many>`:) - any level of includes is now supported (tested with 4);
12+
* View Classes generics (Detail View and List View);
13+
* View Classes now use instance-level methods (breaking change, previously ``classmethods`` were used);
14+
* Pydantic schemas now have to be inherited from custom BaseModel methods (breaking change
15+
, previously all schemas were supported
16+
). It uses custom :ref:`registry class <https://github.com/mts-ai/FastAPI-JSONAPI/blob/188093e967bb80b7a1f0a86e754a52e47f252044/fastapi_jsonapi/schema_base.py#L33>`:
17+
, so we can collect and resolve all schemas. Maybe there's some workaround to collect all known schemas;
18+
* Improved docs, request and response examples have more info, more schemas appear in docs;
19+
* Reworked schemas resolving and building;
20+
* Fixed filtering (schemas resolving fix);
21+
* Fixed filtering (schemas resolving fix);
22+
* Create custom sql filters :ref:`example <custom_sql_filtering>`:;
23+
* Add linters: black, ruff;
24+
* Add pre-commit;
25+
* Add autotests with pytest;
26+
* Add poetry, configure dependencies groups;
27+
* Add GitHub Action with linting and testing;
28+
* Upgrade examples;
29+
* Update docs.
30+
31+
- `@mahenzon`_
32+
1133

1234
**0.2.1**
13-
=========
35+
*********
1436

1537
Enhancements and bug fixes
1638
==========================
@@ -19,7 +41,7 @@ Enhancements and bug fixes
1941

2042

2143
**0.2.0**
22-
=========
44+
*********
2345

2446
Enhancements and bug fixes
2547
==========================
@@ -29,3 +51,4 @@ Enhancements and bug fixes
2951

3052

3153
.. _`@znbiz`: https://github.com/znbiz
54+
.. _`@mahenzon`: https://github.com/mahenzon

docs/custom_filter_example.rst

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
.. _custom_sql_filtering:
2+
3+
Custom SQL filtering
4+
####################
5+
6+
.. currentmodule:: fastapi_jsonapi
7+
8+
Sometimes you need custom filtering that's not supported natively.
9+
You can define new filtering rules as in this example:
10+
11+
12+
13+
Prepare pydantic schema which is used in RoutersJSONAPI as schema
14+
-----------------------------------------------------------------
15+
16+
17+
``schemas/picture.py``:
18+
19+
.. literalinclude:: ../examples/custom_filter_example.py
20+
:language: python
21+
22+
23+
Declare models as usual, create routes as usual.
24+
25+
Search for objects
26+
------------------
27+
28+
29+
.. note::
30+
Note that url has to be quoted. It's unquoted only for an example
31+
32+
Request:
33+
34+
.. sourcecode:: http
35+
36+
GET /pictures?filter=[{"name":"picture.meta","op":"jsonb_contains","val":{"location":"Moscow"}}]
37+
Accept: application/vnd.api+json
38+
39+
Filter value has to be a valid JSON:
40+
41+
.. sourcecode:: JSON
42+
[
43+
{
44+
"name":"picture.meta",
45+
"op":"jsonb_contains",
46+
"val":{
47+
"location":"Moscow"
48+
}
49+
}
50+
]

docs/include_many_to_many.rst

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,120 @@
11
.. _include_many_to_many:
22

3-
Include related M2M
4-
===================
3+
Include nested and related Many-to-Many
4+
#######################################
55

66
.. currentmodule:: fastapi_jsonapi
77

8-
The same as usual includes. Here's an example with an association object:
8+
The same as usual includes. Here's an example with an association object.
99

1010
Example (sources `here <https://github.com/mts-ai/FastAPI-JSONAPI/tree/main/examples/api_for_sqlalchemy>`_):
1111

12+
Prepare models and schemas
13+
==========================
14+
1215

1316
Define SQLAlchemy models
14-
~~~~~~~~~~~~~~~~~~~~~~~~
17+
------------------------
18+
1519

16-
Parent:
20+
Parent model
21+
^^^^^^^^^^^^
22+
23+
``models/parent.py``:
1724

1825
.. literalinclude:: ../examples/api_for_sqlalchemy/models/parent.py
1926
:language: python
2027

2128

22-
Child:
29+
30+
Child model
31+
^^^^^^^^^^^
32+
33+
``models/child.py``:
2334

2435
.. literalinclude:: ../examples/api_for_sqlalchemy/models/child.py
2536
:language: python
2637

2738

28-
Parent to Child Association object:
39+
40+
Parent to Child Association model
41+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
43+
``models/parent_child_association.py``:
2944

3045
.. literalinclude:: ../examples/api_for_sqlalchemy/models/parent_child_association.py
3146
:language: python
3247

3348

3449

50+
3551
Define pydantic schemas
36-
~~~~~~~~~~~~~~~~~~~~~~~
52+
-----------------------
3753

3854

39-
Parent Schema:
55+
Parent Schema
56+
^^^^^^^^^^^^^
57+
58+
``schemas/parent.py``:
4059

4160
.. literalinclude:: ../examples/api_for_sqlalchemy/models/schemas/parent.py
4261
:language: python
4362

4463

45-
Child Schema:
64+
Child Schema
65+
^^^^^^^^^^^^
66+
67+
``schemas/child.py``:
4668

4769
.. literalinclude:: ../examples/api_for_sqlalchemy/models/schemas/child.py
4870
:language: python
4971

5072

51-
Parent to Child Association Schema:
73+
Parent to Child Association Schema
74+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
75+
76+
``schemas/parent_child_association.py``:
5277

5378
.. literalinclude:: ../examples/api_for_sqlalchemy/models/schemas/parent_child_association.py
5479
:language: python
5580

5681

5782

5883

84+
Define view classes
85+
-------------------
86+
87+
88+
Base Views
89+
^^^^^^^^^^
90+
91+
``api/base.py``:
92+
93+
.. literalinclude:: ../examples/api_for_sqlalchemy/api/base.py
94+
:language: python
95+
96+
97+
Parent Views
98+
^^^^^^^^^^^^
99+
100+
``schemas/child.py``:
101+
102+
.. literalinclude:: ../examples/api_for_sqlalchemy/api/parent.py
103+
:language: python
104+
105+
106+
Child Views
107+
^^^^^^^^^^^
108+
109+
``schemas/child.py``:
110+
111+
.. literalinclude:: ../examples/api_for_sqlalchemy/api/child.py
112+
:language: python
113+
114+
115+
59116
List Parent objects with Children through an Association object
60-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
117+
---------------------------------------------------------------
61118

62119
Request:
63120

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ FastAPI-JSONAPI with FastAPI.
6060
filtering
6161
include_related_objects
6262
include_many_to_many
63+
custom_sql_filtering
6364
sparse_fieldsets
6465
pagination
6566
sorting

docs/installation.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ The development version can be downloaded from `its page at GitHub
1515

1616
git clone https://github.com/mts-ai/FastAPI-JSONAPI.git
1717
cd fastapi-jsonapi
18-
python3 -m venv venv
19-
. ./venv/bin/activate
20-
pip install -U pip
21-
python setup.py install
22-
pip install -r requirements-dev.txt
18+
poetry install poetry install --all-extras
2319

2420
.. note::
2521

2622
If you don't have virtualenv please install it
2723

2824
$ pip install virtualenv
25+
26+
If you don't have poetry please install it
27+
28+
$ pip install poetry

examples/api_for_sqlalchemy/models/schemas/child.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ class ChildBaseSchema(BaseModel):
55
"""Child base schema."""
66

77
class Config:
8-
"""Pydantic schema config."""
9-
108
orm_mode = True
119

1210
name: str
@@ -21,11 +19,6 @@ class ChildInSchema(ChildBaseSchema):
2119

2220

2321
class ChildSchema(ChildInSchema):
24-
"""PostComment item schema."""
25-
26-
class Config:
27-
"""Pydantic model config."""
28-
29-
orm_mode = True
22+
"""Child item schema."""
3023

3124
id: int

examples/api_for_sqlalchemy/models/schemas/parent.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ class ParentBaseSchema(BaseModel):
1010
"""Parent base schema."""
1111

1212
class Config:
13-
"""Pydantic schema config."""
14-
1513
orm_mode = True
1614

1715
name: str
@@ -26,15 +24,9 @@ class ParentInSchema(ParentBaseSchema):
2624

2725

2826
class ParentSchema(ParentInSchema):
29-
"""PostComment item schema."""
30-
31-
class Config:
32-
"""Pydantic model config."""
33-
34-
orm_mode = True
27+
"""Parent item schema."""
3528

3629
id: int
37-
3830
children: List["ParentToChildAssociationSchema"] = Field(
3931
relationship=RelationshipInfo(
4032
resource_type="parent_child_association",

examples/custom_filter_example.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from typing import Any
2+
3+
from pydantic.fields import Field, ModelField
4+
from sqlalchemy.orm import InstrumentedAttribute
5+
6+
from fastapi_jsonapi.schema_base import BaseModel
7+
8+
9+
def jsonb_contains_sql_filter(
10+
schema_field: ModelField,
11+
model_column: InstrumentedAttribute,
12+
value: dict[Any, Any],
13+
operator: str,
14+
) -> tuple[Any, list[Any]]:
15+
"""
16+
Any SQLA (or Tortoise) magic here
17+
18+
:param schema_field:
19+
:param model_column:
20+
:param value: any dict
21+
:param operator: value 'jsonb_contains'
22+
:return: one sqla filter and list of joins
23+
"""
24+
filter_sqla = model_column.op("@>")(value)
25+
return filter_sqla, []
26+
27+
28+
class PictureSchema(BaseModel):
29+
"""
30+
Now you can use `jsonb_contains` sql filter for this resource
31+
"""
32+
33+
name: str
34+
meta: dict[Any, Any] = Field(
35+
default_factory=dict,
36+
description="Any additional info in JSON format.",
37+
example={"location": "Moscow", "spam": "eggs"},
38+
_jsonb_contains_sql_filter_=jsonb_contains_sql_filter,
39+
)

0 commit comments

Comments
 (0)