marshmallow
marshmallow copied to clipboard
Make context available to callable `missing`
Related: https://github.com/marshmallow-code/marshmallow/issues/394. I was hoping to use the context
dictionary to drive field logic, but I was disappointed to find that when using the missing
parameter as a callable function, there is no avenue for accessing the context
data.
I'd like to propose feeding the context
dictionary as a parameter to the missing
callable (unfortunately this would be a breaking change).
The rationale:
- The purpose behind
context
(if I am not mistaken) is to provide information to drive logic within a Field/Schema's methods. - The purpose behind the
missing
callable is to support an asynchronous/callback mechanism to allow the missing value to be determined/defined after the field has been instantiated (i.e. during load/parse time). - To support both of the above purposes, I would think it appropriate to provide the
context
when calling themissing
callable.
Below is a somewhat simplified example of what I would like to achieve.
In this specific case I have a custom field where I can define the missing
callback on the Field itself, and have the context
be provided to it.
class UserId(marshmallow.fields.Str):
def __init__(self, *args, **kwargs):
kwargs["missing"] = self._get_missing
super(UserId, self).__init__(*args, **kwargs)
@classmethod
def _get_missing(cls, context):
return context["user_id"]
Add it to a simple UserSchema... (note that the missing
parameter is not specified in the UserId
instantiation)
class UserSchema(marshmallow.Schema):
id = UserId()
And then parse...
import flask
from myapp import authenticate
schema = UserSchema()
schema.context = authenticate() # injects user information (e.g the user's actual id)
parsed = schema.load({}) # note the empty dictionary, thereby invoking the field's `missing` callable
# parsed {id: "302339403"} # sweet, the `missing` callback populated the id for us!
Obviously the missing
callable does not need to be defined as method on the field, but I figured this implementation might turn some gears for other potential solutions.
I'm a noob to marshmallow, so perhaps there are better ways to skin/think about this. Much appreciated!
And thank your for all of your work!
Apologies for the delayed response.
This is similar to #289 . I'm considering if we should add something along the lines of DRF's API for opting into context for validation and default functions: https://www.django-rest-framework.org/community/3.11-announcement/#validator-default-context .
In the meantime, I like the workaround you described.
I think the context feature rework proposed in #1826 would solve this.