Hello, after a whole week trying different approaches I finally went with 
using BeforeEvent subscriber + a view deriver to add specific option on 
`request.environ` about which ones should enhance the response:

def my_view_deriver(view, info):
    def wrapper(context, request):
        if 'enhance_response' in info.options:
            request.environ['enhance_response'] = True
        return view(context, request)
    return wrapper

config.add_view_deriver(my_view_deriver)

@subscriber(BeforeEvent)
def enhance_response(event):
    request = event.get('request')
    if request.environ.get('enhance_response'):
        event.rendering_val = {
             'extra_key': 'something',
             'former_response': event.rendering_val,
        }
   # no need to return anything here

@view_config(..., enhance_response=True)
def my_view(context, request):
    return {'response': 'whatever'}


And that's it!
El jueves, 11 de abril de 2024 a la(s) 4:55:56 p.m. UTC-3, Jonathan Vanasco 
escribió:

> I don't know what is recommended, but have done similar things before.
>
> One way I've done something similar is to use a custom renderer in the 
> `@view_config`.
>
> Another way I've accomplished this is to set a request attribute early on 
> - either in a tween or in the view class instantiation or even a request 
> attribute, and having my return value reflect this.
>
> To illustrate the second example, in this project each view is configured 
> to handle 2 different API endpoints - one that is human HTML, and another 
> that is programmatic API for JSON.  If the route is accessed for JSON, the 
> view returns a slightly different payload.
>
> 1- This code adds a "Request.wants_json" attribute:
>
>
> https://github.com/aptise/peter_sslers/blob/main/src/peter_sslers/web/__init__.py#L136-L140
>
> 2- This view returns a different payload, depending upon the wants_json 
> attribute.
>
>
> https://github.com/aptise/peter_sslers/blob/main/src/peter_sslers/web/views_admin/acme_challenge.py#L114-L126
>
> This was a quick, lazy and functional way to proceed.  If I had to do this 
> again, I would probably use a single payload with a custom JSON renderer, 
> and have a function in the custom JSON renderer to only render specific 
> values from the payload (which would either be attached to the request, or 
> listed in a namespace in the payload).
>
> For your description though, I would probably just write a custom JSON 
> renderer.
>
> For example, here is a custom jsonp and gif renderer:
>
> def jsonp_renderer_factory(info):
>     def _render(value, system):
>         value = py2json(value)
>         request = system.get("request")
>         if request is None:
>             return value
>         # JSONP is GET only, unless you do some weird shit that doesn't 
> work reliably
>         callback = request.GET.get("callback", None)
>         if callback is None:
>             ct_json = "application/json"
>         else:
>             ct_json = "application/javascript"
>             value = "%s(%s)" % (callback, value)
>         response = request.response
>         if response.content_type == response.default_content_type:
>             response.content_type = ct_json
>         return value
>
>     return _render
>
> def gif_renderer_factory(info):
>     def _render(value, system):
>         request = system.get("request")
>         if request is not None:
>             response = request.response
>             ct = response.content_type
>             if ct == response.default_content_type:
>                 response.content_type = "image/gif"
>         return value
>
>     return _render
>
>     config.add_renderer("jsonp", jsonp_renderer_factory)
>     config.add_renderer("gif", gif_renderer_factory)
>
>
>
> On Wednesday, April 10, 2024 at 4:44:27 PM UTC-4 Pablo Díaz Ogni wrote:
>
>> Hello guys! I'm building an API using pyramid + pyramid_openapi3 package 
>> to use openapi3 features such as request validation, the web interface, and 
>> have well documented the endpoints. I'm having trouble understanding the 
>> different ways I can use views, view_derivers, tweens, decorators, etc.
>>
>> Let's say I have multiple views that return its own data as a 
>> dictionary/list and I want to wrap the response with more info before 
>> rendering to JSON:
>> {request: <request_metadata>, response: <the actual data returned by the 
>> view>}
>>
>> I first tried with tweens, but that's post renderization so I have to 
>> deserialize and serialize the json. I also tried view_derivers and I was 
>> facing the same issue. I also saw that you can match a view with a Context 
>> such as an exception, but not sure if there is a way to use that Context in 
>> other way such as "all the View objects that have this specific attribute"
>>
>> I also tried a decorator with wrapper(context, request), but i switched 
>> from functions with @view_config to use View classes with get() method 
>> instead, so I should change the approach of the decorator
>>
>> I'm new to pyramid and it has its own way of plugging views so I would 
>> like to know what is the recommended way of doing this?
>>
>

-- 
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 pylons-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/pylons-discuss/d632b5a2-7323-4d73-8d1f-a1f58c13f897n%40googlegroups.com.

Reply via email to