> On May 6, 2018, at 14:27, Jonathan Vanasco <[email protected]> wrote: > > I'm doing some housekeeping on an app that has been a bit too lax on keeping > to it's own coding standards. > > There have been a bunch of updates over the past few years to the views > systems, so I'm hoping something may work for our needs... > > In a handful of sections, it utilize class based views that rely on > inheritance for setup routines. > > for example... > > > class Foo(object): > def __init__(self, request): > self.request = request > ... common setup ... > > @view_config(route_name="bar",) > def bar(self): > pass > > I was wondering if it is possible to hook into pyramid after the Foo() is > instantiated, but before `Foo.bar` is called. > > What I want to accomplish, in case someone has a better suggestion: > > * The views i'm dealing with generally handle form processing on an API. > * There are a handful of common setup and form validation routines that > happen on these > * I'd like to define and trigger the common validation in a parent class, to > ensure it runs. a handful of views were not calling the correct validation > routines, because people make easy mistakes like that.
Create a view deriver that is used to do the processing before entering the view, allowing you to pass a validation routine to the @view_config instance that validates? Have it raise at config time if there is no validation routine defined for that view? > * I could integrate this processing into __init__, but error reporting would > be much easier if it occurs after __init__, so I can utilize the class > instance. If you want to do this you'd have to replace the default view mapper to do the extra work here: https://github.com/Pylons/pyramid/blob/master/pyramid/viewderivers.py#L114-L139 <https://github.com/Pylons/pyramid/blob/master/pyramid/viewderivers.py#L114-L139> This deals with instantiating the class and calling the view (either the view attribute or __call__ on the instantiated class). I'd recommend going with a view deriver... > > > > -- > You received this message because you are subscribed to the Google Groups > "pylons-discuss" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected] > <mailto:[email protected]>. > To post to this group, send email to [email protected] > <mailto:[email protected]>. > To view this discussion on the web visit > https://groups.google.com/d/msgid/pylons-discuss/ee79f36e-f7f1-4f75-abb3-d4e31ca879f0%40googlegroups.com > > <https://groups.google.com/d/msgid/pylons-discuss/ee79f36e-f7f1-4f75-abb3-d4e31ca879f0%40googlegroups.com?utm_medium=email&utm_source=footer>. > For more options, visit https://groups.google.com/d/optout > <https://groups.google.com/d/optout>. For example: import logging from pyramid.path import DottedNameResolver from marshmallow import Schema >From . import ValidationFailure log = logging.getLogger(__name__) # request.cstruct validation def validation_view(view, info): if info.options.get('validator'): name_resolver = DottedNameResolver(info.package) validator = name_resolver.maybe_resolve(info.options.get('validator')) # If the validator is a subclass of Schema, we assume we need to create # it and that it has a load function that returns a tuple of # data/errors if issubclass(validator, Schema): def wrapped_validator(jstruct): (data, errors) = validator().load(jstruct) # The validator should probably raise by itself... if errors: log.debug(errors) raise ValidationFailure(errors) return data validator_func = wrapped_validator else: validator_func = validator def wrapper_view(context, request): try: jstruct = request.json_body except ValueError as e: log.debug(e) raise HTTPBadRequest({'error': 'Expecting JSON. Didn\'t work out.'}) if jstruct: request.appstruct = validator_func(jstruct) return view(context, request) return wrapper_view return view validation_view.options = ('validator',) Add it to your config: # Add the validator view deriver config.add_view_deriver('.validation.validation_view') And here is a sample view: @view_config( name='forgot', request_method='POST', validator='myproject.validation.user.Email', ) def forgot(self): request = self.request dbsession = request.dbsession appstruct = request.appstruct user = dbsession.query(m.User)\ .filter(m.User.email == appstruct['email'])\ .one_or_none() if user is not None: request.notify(e.UserForgotPassword(request, user)) return HTTPNoContent() In my case I also allow you to pass a function that validates the input instead of a Marshmallow schema, but the schema works really well for most of my API endpoints. You could off course replace it with Colander or any other validator. Currently the view deriver just returns the normal view if there is no validator specified, but you could also raise a ConfigError or something similar, you may also require multiple options so you can for example turn off validation for a particular view. Do note that ValidationFailure takes the marshmallow errors/or your validation function's output and I have a special view that handles ValidationFailures by turning them into HTTPBadRequest's with extra information on what part of the validation failed/why. Anyway, you get the basic gist of it and hopefully this helps you find a solution to your problem. Bert JW Regeer -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/DC8B90FA-EDE8-4A72-B272-F114758E34BA%400x58.com. For more options, visit https://groups.google.com/d/optout.
