Skip to content

Commit 6da9723

Browse files
committed
Update docs and bump dev version
- Update changelog - Add @DamianHeard to AUTHORS - Add Schema Factories section to Quickstart - Document `use_args_with` pattern from #73 (comment)
1 parent f77b288 commit 6da9723

File tree

5 files changed

+92
-8
lines changed

5 files changed

+92
-8
lines changed

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ Contributors (chronological)
2020
* Rory Hart <https://github.com/hartror>
2121
* Jace Browning <https://github.com/jacebrowning>
2222
* @marcellarius <https://github.com/marcellarius>
23+
* Damian Heard <https://github.com/DamianHeard>

CHANGELOG.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changelog
22
---------
33

4+
1.1.0 (unreleased)
5+
******************
6+
7+
Features:
8+
9+
* ``Parser.parse``, ``Parser.use_args`` and ``Parser.use_kwargs`` can take a Schema factory as the first argument (:issue:`73`). Thanks :user:`DamianHeard` for the suggestion and the PR.
10+
411
1.0.0 (2015-10-19)
512
******************
613

docs/quickstart.rst

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ Nesting Fields
214214
})
215215
}
216216
217-
Marshmallow Integration
218-
-----------------------
217+
Advanced: Marshmallow Integration
218+
---------------------------------
219219

220220
When you need more flexibility in defining input schemas, you can pass a marshmallow `Schema <marshmallow.Schema>` instead of a dictionary to `Parser.parse <webargs.core.Parser.parse>`, `Parser.use_args <webargs.core.Parser.use_args>`, and `Parser.use_kwargs <webargs.core.Parser.use_kwargs>`.
221221

@@ -254,6 +254,81 @@ When you need more flexibility in defining input schemas, you can pass a marshma
254254
.. note::
255255
You should always set ``strict=True`` (either as a ``class Meta`` option or in the Schema's constructor) when passing a schema to webargs. This will ensure that the parser's error handler is invoked when expected.
256256

257+
258+
Advanced: Schema Factories
259+
--------------------------
260+
261+
If you need to parametrize a schema based on a given request, you can use a "Schema factory": a callable that receives the current `request` and returns a `marshmallow.Schema` instance.
262+
263+
Consider the following use cases:
264+
265+
- Handle partial updates for PATCH requests using marshmallow's `partial loading <https://marshmallow.readthedocs.org/en/latest/quickstart.html#partial-loading>`_ API.
266+
- Filtering via a query parameter by passing ``only`` to the Schema.
267+
268+
.. code-block:: python
269+
270+
from marshmallow import Schema, fields
271+
from webargs.flaskparser import use_args
272+
273+
class UserSchema(Schema):
274+
id = fields.Int(dump_only=True)
275+
username = fields.Str(required=True)
276+
password = fields.Str(load_only=True)
277+
first_name = fields.Str(missing='')
278+
last_name = fields.Str(missing='')
279+
date_registered = fields.DateTime(dump_only=True)
280+
281+
class Meta:
282+
strict = True
283+
284+
def make_user_schema(request):
285+
# Filter based on 'fields' query parameter
286+
only = request.args.get('fields', None)
287+
# Respect partial updates for PATCH requests
288+
partial = request.method == 'PUT'
289+
# Add current request to the schema's context
290+
return UserSchema(only=only, partial=partial, context={'request': request})
291+
292+
# Pass the factory to .parse, .use_args, or .use_kwargs
293+
@use_args(make_user_schema):
294+
def profile_view(args):
295+
# ...
296+
297+
298+
Reducing Boilerplate
299+
++++++++++++++++++++
300+
301+
We can reduce boilerplate and improve [re]usability with a simple helper function:
302+
303+
.. code-block:: python
304+
305+
from webargs.flaskparser import use_args
306+
307+
def use_args_with(schema_cls, schema_kwargs=None, **kwargs):
308+
schema_kwargs = schema_kwargs or {}
309+
def factory(request):
310+
# Filter based on 'fields' query parameter
311+
only = request.args.get('fields', None)
312+
# Respect partial updates for PATCH requests
313+
partial = request.method == 'PUT'
314+
# Add current request to the schema's context
315+
# and ensure we're always using strict mode
316+
return schema_cls(
317+
only=only, partial=partial, strict=True,
318+
context={'request': request}, **schema_kwargs
319+
)
320+
return use_args(factory, **kwargs)
321+
322+
323+
Now we can attach input schemas to our view functions like so:
324+
325+
.. code-block:: python
326+
327+
@use_args_with(UserSchema)
328+
def profile_view(args):
329+
# ...
330+
331+
257332
Next Steps
258333
----------
259334

webargs/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from webargs.core import argmap2schema, WebargsError, ValidationError
77
from webargs import fields
88

9-
__version__ = '1.0.0'
9+
__version__ = '1.1.0.dev0'
1010
__author__ = 'Steven Loria'
1111
__license__ = 'MIT'
1212

webargs/core.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,8 @@ def _validate_arguments(self, data, validators):
267267
def _get_schema(self, argmap, req):
268268
"""Return a `marshmallow.Schema` for the given argmap and request.
269269
270-
:param argmap: Either a `marshmallow.Schema`, `dict`, or callable that returns
270+
:param argmap: Either a `marshmallow.Schema`, `dict`
271+
of argname -> `marshmallow.fields.Field` pairs, or a callable that returns
271272
a `marshmallow.Schema` instance.
272273
:param req: The request object being parsed.
273274
:rtype: marshmallow.Schema
@@ -283,9 +284,9 @@ def _get_schema(self, argmap, req):
283284
def parse(self, argmap, req=None, locations=None, validate=None, force_all=False):
284285
"""Main request parsing method.
285286
286-
:param argmap: Either a `marshmallow.Schema`, `dict`
287-
of argname -> `marshmallow.fields.Field` pairs, or a callable that returns
288-
a `marshmallow.Schema` instance.
287+
:param argmap: Either a `marshmallow.Schema`, a `dict`
288+
of argname -> `marshmallow.fields.Field` pairs, or a callable
289+
which accepts a request and returns a `marshmallow.Schema`.
289290
:param req: The request object to parse.
290291
:param tuple locations: Where on the request to search for values.
291292
Can include one or more of ``('json', 'querystring', 'form',
@@ -350,7 +351,7 @@ def use_args(self, argmap, req=None, locations=None, as_kwargs=False, validate=N
350351
def greet(args):
351352
return 'Hello ' + args['name']
352353
353-
:param dict argmap: Either a `marshmallow.Schema`, a `dict`
354+
:param argmap: Either a `marshmallow.Schema`, a `dict`
354355
of argname -> `marshmallow.fields.Field` pairs, or a callable
355356
which accepts a request and returns a `marshmallow.Schema`.
356357
:param tuple locations: Where on the request to search for values.

0 commit comments

Comments
 (0)