|
| 1 | +import base64 |
| 2 | + |
1 | 3 | from marshmallow import Schema, ValidationError, fields, pre_load, validate, validates |
2 | 4 | from marshmallow_sqlalchemy import SQLAlchemyAutoSchema, SQLAlchemySchema, auto_field |
| 5 | +from sqlakeyset import BadBookmark, unserialize_bookmark |
3 | 6 |
|
4 | 7 | from app.models import Category, Product, Subcategory, User |
5 | 8 |
|
6 | 9 |
|
| 10 | +class Cursor(fields.Field[dict]): |
| 11 | + def _serialize(self, paging, attr, obj, **kwargs): |
| 12 | + def encode(s): |
| 13 | + bytes = s.encode("utf-8") |
| 14 | + return base64.urlsafe_b64encode(bytes).decode("utf-8") |
| 15 | + |
| 16 | + if paging is None: |
| 17 | + return None |
| 18 | + |
| 19 | + return { |
| 20 | + "next": encode(paging.bookmark_next) if paging.has_next else None, |
| 21 | + "prev": encode(paging.bookmark_previous) if paging.has_previous else None, |
| 22 | + } |
| 23 | + |
| 24 | + def _deserialize(self, cursor, attr, data, **kwargs): |
| 25 | + if cursor is None: |
| 26 | + return None |
| 27 | + |
| 28 | + try: |
| 29 | + decoded_bytes = base64.urlsafe_b64decode(cursor.encode("utf-8")) |
| 30 | + marker_serialized = decoded_bytes.decode("utf-8") |
| 31 | + return unserialize_bookmark(marker_serialized) |
| 32 | + except (TypeError, ValueError, KeyError, BadBookmark) as ex: |
| 33 | + raise ValidationError("Invalid cursor") from ex |
| 34 | + |
| 35 | + |
7 | 36 | class CategoryOut(SQLAlchemyAutoSchema): |
8 | 37 | class Meta: |
9 | 38 | model = Category |
@@ -70,6 +99,7 @@ class Meta: |
70 | 99 |
|
71 | 100 | class ProductsOut(Schema): |
72 | 101 | products = fields.List(fields.Nested(ProductOut)) |
| 102 | + cursor = Cursor(required=False) # require false for getting product by name |
73 | 103 |
|
74 | 104 |
|
75 | 105 | class ProductIn(SQLAlchemySchema): |
@@ -100,7 +130,7 @@ class NameArgs(Schema): |
100 | 130 |
|
101 | 131 |
|
102 | 132 | class PaginationArgs(Schema): |
103 | | - page = fields.Int(load_default=1) |
| 133 | + cursor = Cursor(load_default=None) |
104 | 134 |
|
105 | 135 |
|
106 | 136 | class AuthIn(SQLAlchemySchema): |
|
0 commit comments