Jinja template from user-uploaded "attached" html files

Looking to override “templates/base.html” for webpages using a template file that is user-uploaded as an attachment on a production server and therefore not part of the original codebase. The idea is to provide a means to create templates “on the fly” by various team members.

I’m considering doing this two ways,

  1. to override the base template with context.base_template = 'path/to/file/upload.html',

  2. and/or in the Jinja for the current page using {% extends "path/to/file/upload.html" %}.

I’ve not been able to properly test either approach because when doing so, for {% extends … } I get an error that the template file could not be found:

ja2.exceptions.TemplateNotFound: path/to/file/upload.html

When I use comments or directly assigning a path to context.base_template, there is no exception and nothing seems to happen at all.

My ask for help is, therefore:

  1. what is the appropriate server-visible path to user-uploaded files (public, or private)?

  2. if that path must include the current site name, or app name, etc., how should I resolved those parts of the path (i.e. for … frappe-bench/sites/[sitename]/public/files … if this is were the correct path, how can I resolve the [sitename] in jinja)?

  3. Should I be doing this an entirely different way, such as by using the templates doctype, and if so, how would I reference such a template either from the context python for the webpage using context.base_template, or in the jinja markup using {% extends ... } ?

Thank you for your help!

I think the right answer to the “what is the best way to do this” depends on how many users and the frequency with which they will be uploading templates. The idea of uploading an HTML file to the server is not idiomatic to Frappe (but very likely is in what ever framework you’re coming from). When I’m in doubt about the right way to design a solution I try to take the perspective of “if this were a feature on erpnext.com, how would it be solved, if at all”.

With that in mind, I think you want to store your templates serialized in the DB, the same way that print formats, email templates and webpages are. Doing it as a file upload would be a middle ground but likely not offer you all the flexibility you’d be looking for. You can then dynamically fetch them with a jinja method included in hooks.py.

Thanks, tmatteson. I appreciate your reply here.

Though I agree with your reasoning, we may look to leverage overriding the template chain for a webpage Doctype using the context editor in Desk to assign context.base_template to a user-uploaded file acting as a template file, for example ‘/public/files/template.html’

But we aren’t able to get this working, and it seems like it is because we aren’t getting the path to the file right. We’ve experimented with using context.base_template = frappe.utils.get_files_path('template.html') but this isn’t working.

Any thoughts here? Looking do create a proof of concept for the approach, even though it may be odd.

Thanks in advance!

Here’s something to try, I haven’t tested it.
Override a template in {my_app}/www/template_here.html.
Add a symlink from {my_app}/www/ to ./sites/{site name}/public/{www}.
Users upload an HTML file into the www directory of the file manager.
I’m certain I can design and build a better solution; get in touch if you’re interested in exploring that.