More than one template for an action

210 views
Skip to first unread message

Sundararajan Seshadri

unread,
Sep 8, 2022, 7:00:32 AM9/8/22
to py4web
If I have to route output to different templates, depending on some value, how do I specify the template? Is there an option to 'render' on the specific spot using just the template name (and not the full path) instead of specifying @action.uses?

Alexander Beskopilny

unread,
Sep 8, 2022, 7:38:18 AM9/8/22
to py4web
1 controllers.py

@action('multihtml')
@action.uses('multihtml.html')
def multihtml():
    message = 'multihtml'
    x= 't1'
    y= 't2'
  
    if ....:
         return dict(y=y , message=message)
   else:
         return dict( x =x , message=message )


2 templates/multihtml.html

[[extend 'layout.html']]

<div class="section">
  <div class="vars">
      [[=message]]
  </div>
</div>


 [[if locals().get('x'): ]]
   <p> html1 [[=x ]] </p>
   [[ include 'x.html'  ]]

 [[elif locals().get('y'): ]]
   [[ include ''y.html ]
   <p>html2 [[=y ]]</p>
 [[pass]]


should work

Sundararajan Seshadri

unread,
Sep 8, 2022, 7:47:35 AM9/8/22
to py4web
Thanks. Essentially you are saying that we resolve it in the template file. The only issue with that is that template file is going to be a large one. Ideally I preferred something like what was available in web2py: response.view. That is,

if t1:
  response.view = 'html1.html'
  return dict(...)
else:
 response.view='html2.html'
 return dict(..)

Thanks anyway, for the interest. Appreciate it.

Jim Steil

unread,
Sep 8, 2022, 8:20:44 AM9/8/22
to py4web
I haven't found a way to do that in py4web like you could in web2py.

Instead I just redirect to a different controller method.

if not t1:
    redirect(URL('controller_method_2'))

return dict(...)

-Jim

Sundararajan Seshadri

unread,
Sep 8, 2022, 8:57:01 AM9/8/22
to py4web
Yes. It is an alternative. But the pain is when you have to transfer / share a lot of values between actions through Session variables, I guess. Thanks for the answer.

Alexander Beskopilny

unread,
Sep 8, 2022, 9:08:49 AM9/8/22
to py4web
from examples

@action("page_with_postback", method=["GET", "POST"])
def page_with_postback():
    return (
        "<html><body><pre>%s</pre>"
        + '<form method="POST" action="%s" enctype="multipart/form-data">'
        + '<input type="hidden" name="data" value="dummy"/>'
        + "<button>Click</button></form></body></html"
    ) % (dict(request.forms), URL("page_with_postback"))

also,  frome some code

from renoir import Renoir
.......
async def video_home(request):
    template = Renoir(delimiters=('[[', ']]'))
    return HTMLResponse ( template._render(source = webm_html , context=menu_vars, ) )

you can do something like this

Jim Steil

unread,
Sep 8, 2022, 9:23:21 AM9/8/22
to py4web
I would just pass them as vars on the URL() call.

Here is an example 
URL("my_other_endpoint", vars=dict(var1=var1, var2=var2, var3=var3))

-Jim

Massimo

unread,
Sep 8, 2022, 10:12:55 AM9/8/22
to py4web
This is possible and I would not recommend using if statements in the template itself nor using low level Renoir because it will not work quite the same. Instead you can do:

from py4web.core import Template, action

def render_template(data, html):
    context = dict(output=data)
    Template(html).on_success(context)
    return context['output']

@action('index')
def index():
     d = dict(a='hello', b='world')
     return render_template(d, 'generic.html')

Maybe I will add a method render_template to core that works like above.

Sundararajan Seshadri

unread,
Sep 9, 2022, 3:18:53 AM9/9/22
to py4web
Thanks Massimo. This is a fantastic product and a more-fantastic group.  Thanks every one for the quick response and desire to help. 

Massimo DiPierro

unread,
Sep 9, 2022, 3:29:23 AM9/9/22
to Sundararajan Seshadri, py4web
it is. 😀

i forgot to mention, there is some small overhead in creating a Template(filename) at every request. so if you have a fixed set of template files you may want to put your template objects in a dict mapping {filename:Template(filename)} and retrieve them inside the render function 

--
You received this message because you are subscribed to the Google Groups "py4web" group.
To unsubscribe from this group and stop receiving emails from it, send an email to py4web+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/py4web/2ff27225-56fb-4a1d-9c7f-e698050f6f24n%40googlegroups.com.

Ali

unread,
Oct 26, 2023, 1:07:48 AM10/26/23
to py4web
Just to make sure, the above render_template is not added to core.py yet. Right? 

Jim Steil

unread,
Oct 26, 2023, 7:38:48 AM10/26/23
to py4web
It is not.

At least, not with that name.

-Jim

Ali

unread,
Oct 26, 2023, 7:44:24 PM10/26/23
to py4web
Thank you!

- Ali

Ali

unread,
Oct 29, 2023, 9:36:51 PM10/29/23
to py4web
When using the  render_template function, I encountered two issues, which I've outlined below. Fortunately, I was able to resolve both issues. I have included the solutions I found below as they may help others in the future. I also welcome any feedback on potentially better ways to fix the issues.

1. 
Issue: The newly rendered page shows the user as signed-out. 
Solution: The default sign-in button checks at the top of the page checks for the existence of globals().get('user'). The variable user is not submitted to the HTML file by default when using render_template. To resolve the issue, simply add user=auth.user in the data dictionary inputted to the render_template function.

2. 
Issue: The URL shown in the browser address bar does not change as the page content changes with the application of render_template.
Solution. The JavaScript command window.history.pushState can be used to manually update the URL.
Reply all
Reply to author
Forward
0 new messages