setting a dynamic data attribute on flask wtforms jinja select - flask

Have a flask wtforms select field and trying to incorporate htmx ajax call, which has dashes in data attributes so I found a solution on SO like the following:
{{ form.dia(class="form-select", **{'hx-post': "/pulleys/{{pulley_id}}/hub_type", 'hx-target': "#hub-shaft-selection", 'hx-swap': "innerHTML"}) }}
but the {{pulley_id}} doesn't get parsed by the template, I guess it's already inside another {{ }}.
Is there a way to build the dynamic part as shown above so it ends up as
'hx-post'="/pulleys/1/hub_type"
when fully rendered for pulley_id=1

If pulley_id is a variable either inside a loop or passed into render_template your should be able to format the string:
{{ form.dia(class_="form-select", **{'hx-post': "/pulleys/%s/hub_type"|format(pulley_id), 'hx-target': "#hub-shaft-selection", 'hx-swap': "innerHTML"}) }}
Note: you also want class_ not class if you're trying to set the HTML class attribute.

Related

WTForms use quotes in Jinja2

I've got the following WTForms class:
from flask_wtf import FlaskForm
from wtforms import SelectField
class MonitorLevel(FlaskForm):
monitor = SelectField('Monitor', choices=MONITOR_CHOICES)
Which can be rendered using the following jinja2-code:
{{ form.monitor() }}
However, I want to execute a JS-script when the value changes, so I've added the following:
{{ form.monitor(**{'onchange': 'sendForm();'}) }}
Which works fine, but now I want to pass a variable (which is a string), as an argument:
{{ form.monitor(**{'onchange': 'sendForm("{}");'.format(variable)}) }}
However, this renders as:
<select id="monitor" name="monitor" onchange="sendForm("name");">...</select>
So, I tried to escape this using the safe function, but this doesn't work. I've also tried to escape the quote by: \", but that doesn't work as well.
Any ideas of adding a quote in the value of the dict?
Thanks in advance,
From the WTForms documentation https://wtforms.readthedocs.io/en/2.3.x/widgets/#widget-building-utilities :
WTForms uses MarkupSafe to escape unsafe HTML characters before rendering. You can mark a string using markupsafe.Markup to indicate that it should not be escaped.
Without using markupsafe.Markup I had the same error:
{{ input_field(**{'#click': '"show=true"'})|safe }}
gives
<input #click=""show=true"">
instead of
<input #click="'show=true'">
Using the markupsafe module inside the Jinja2 template:
{{ input_field(**{'#click': markupsafe.Markup("show=true")})|safe }}
does the job:
<input #click="show=true">
Be careful: WTForm encloses the string in the double quotes ", so you need to take a usual care about the " inside your string.
BAD WAY
{{ input_field(**{'#click': markupsafe.Markup('console.log("show=true")')})|safe }}
will result in
<input #click="console.log("show=true")">
which is wrong (one string is not inside the other).
GOOD WAY
{{ input_field(**{'#click': markupsafe.Markup("console.log('show=true')")})|safe }}
will give
<input #click="console.log('show=true')"
This behavior is normal, WTForms use escape(s, quote=True) to render HTML attributes values (escape documentation)
You can look function def html_params(**kwargs): on Github directly fore more informations.
Basically you don't have to change your code because :
Javascript still works like a charm, your browser transforms HTML entities on the fly (sendForm() is run onchange).
onchange="sendForm("name");" is NOT valid HTML attribute if you print it without escape(s, quote=True).

Django Form Name as Attribute in HTML Template

I have an attribute of objects that can be rendered in html template like this :
{{ mymodels.something }}
In my case, i have forms containing an input field that has name similar with "something", so i want to run something like this in my template:
{% for form in my_form %}
{{ mymodels.form.name }} <!-- is same as mymodels.something -->
{% endfor %}
but it can't be rendered..
How can i do something like that?
Forms are something to gather data on client side - send it over to server side which validates them and does something with them (e.g. writing into models, or maybe passing it back into the context of your next rendering).
When your template is rendered, it also renders your form (building the markup, providing initial values) - when the template engine finished it's job, the HTML code is sent to the browser.
If you want to access form data on rendering time, there will always be the same value: the initial value. Which does not make much sense. As you might just pass the same data to your rendering context and use it from there.
Read the docs for further information on forms, especially the part rendering fields manually might interest you - if your question aims into this direction.

django form field label as html

I am loading a form using following template tag -
{{ form.as_table }}
Form got radio button, and the select items for it got using following form field -
forms.RadioSelect(choices=[ (o.choice_value, o.choice_name) for o in Choice.objects.filter()])
one of the choice_name got html elements into it, which gets loaded with those tags instead of actual HTML rendering.
If it would be regular template variable, I can do {{ some_variable|safe }} to load it as HTML, any idea how to do it in case of form tag.
You can use template tags and filters anywhere in your Python code, just import them and use them:
from django.template.defaultfilters import safe
forms.RadioSelect(choices=[(o.choice_value, safe(o.choice_name))
for o in Choice.objects.filter()])

Dynamically set default form values in django

I'm trying to find a way to dynamically set default form values. So for example, if I add a facebook login feature on my webpage, and I can get his first name and last name from what the facebook javascript returns, I want to be able to set these values as the new "value" parameter in the given form. (basically so I'm able to put the user in my database)
I was hoping that there is some sort of
{{ form.firstname.default = Javascript.return.firstname }}
that I can insert into a template but there isn't...
Any ideas? Thank you.
Edit;; Maybe it would be better to first pass in the information into a views.py? But how would I do this? I am just considering hand writing the inputs out in the javascript field, which would be annoying...
You can set the default value of a template variable:
{{ form.firstname|default:Javascript.return.firstname }}
assuming that {{ Javascript.return.firstname }} is valid in that template context.
The code generated by Django is all server-side, its templates can't use anything which isn't available when the page is loaded. You need to use javascript to set the value.
For example, if your form looks like this:
<form id="login">
<input name="firstname" />
</form>
You could use this javascript (assuming you're using jQuery):
// Do the facebook login, set the var fname to the first name, then:
$('#login [name=firstname]').val(fname);

Django adds %2f in place of the / in the template for an image field

I am having a few issues with a django template with a mimetype="text/plain".
Firstly the s3 part of url is rendering with the :80 on the end and then the actual image url is rendering with '%2f' in replace of each slash.
object.image.url
I have tried safe and other custom tags to replace the '%2f' and it just wont work
#what I have
http://blahblah.s3.amazonaws.com:80/navigation%2Fprimary%2Fimage.jpg
#what I want
http://blahblah.s3.amazonaws.com/navigation/primary/image.jpg
The custom tag I have tried along side safe is:
import re
from django import template
register = template.Library()
def reslash (value):
return value.replace('%2f', '/')
register.filter('reslash', reslash)
used like this:
{{ object.image.url|reslash }}
But it doesn't work. Thanks
Django automatically html escapes all variables in templates. In order to insert the value of a variable without escaping you should use the safe filter to tell django the value does not need to be auto-escaped like so:
{{ object.image.url|safe }}