I've got a custom filter that takes a string and makes it into the appropriate attributes for the tooltip library I'm using. It worked with OpenTip, but I'm converting to using the tooltip library that's in Bootstrap.
Here's my filter:
from django import template
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
register = template.Library()
#register.filter(needs_autoescape=False, is_safe=True)
def tooltip(value, autoescape=False):
"""
Filter to turn some text into the tag that the tooltip library uses -
Written as a filter so we can switch from one tooltip library to
another
"""
if autoescape:
esc = conditional_escape
else:
esc = lambda x: x
if value is not None and len(value) > 0:
retval = 'data-toggle="tooltip" data-html="true" ' +\
'rel="tooltip" title="%s"' % esc(value)
return mark_safe(retval)
else:
return ''
And here's where I'm using it in a template:
<form id="filter" name="filter" method="post"
class="form-inline">
{% csrf_token %}
<label for="filterText">Filter Query:</label>
<input type="text" id="current_filter" name="current_filter" value="{{current_filter}}" placeholder="Filter" class="span8"/>
<i class="icon-question-sign"
{{"Filters -<br>requester: [[first] [last]]|[windows_id]<br>client: [[first] [last]]|[windows_id]<br>approver: [[first] [last]]|[windows_id]<br>worker: [[first] [last]]|[windows_id]<br>ticket: [id]<br>status: [open]|[closed]|[hold]<br>type: [termination]|[extension]|[access]|[password]|baskets]<br>item: [name for category/item/attribute inventory]<br>since: [mm/dd/yyyy]|[yyyy-mm-dd]<br>before: [mm/dd/yyyy]|[yyyy-mm-dd]<br>All searchs are AND with comma delimiting"|tooltip}}></i>
<input type="submit" name="btnSubmit" class="btn" value="Filter"/>
<input id="filter_reset" type="button" name="filter_reset" class="btn" value="Clear existing filters"/>
</form>
{% endif %}
But the tooltip isn't processing the html, and when I go into Firebug and cut and paste the html, it looks like something is escaping it in spite of the fact that I marked it with mark_safe:
<form class="form-inline" method="post" name="filter" id="filter">
<input type="hidden" value="dpuAc9GNUQtvGG5wYzrWsG2Vpu5i7PWJ" name="csrfmiddlewaretoken">
<label for="filterText">Filter Query:</label>
<input type="text" class="span8" placeholder="Filter" value="" name="current_filter" id="current_filter">
<i title="Filters -<br>requester: [[first] [last]]|[windows_id]<br>client: [[first] [last]]|[windows_id]<br>approver: [[first] [last]]|[windows_id]<br>worker: [[first] [last]]|[windows_id]<br>ticket: [id]<br>status: [open]|[closed]|[hold]<br>type: [termination]|[extension]|[access]|[password]|baskets]<br>item: [name for category/item/attribute inventory]<br>since: [mm/dd/yyyy]|[yyyy-mm-dd]<br>before: [mm/dd/yyyy]|[yyyy-mm-dd]<br>All searchs are AND with comma delimiting" rel="tooltip" data-html="true" data-toggle="tooltip" class="icon-question-sign">
</i>
<input type="submit" value="Filter" class="btn" name="btnSubmit">
<input type="button" value="Clear existing filters" class="btn" name="filter_reset" id="filter_reset">
</form>
How do I get the html in that filter text into the page without the being escaped?
Try using safe:
{{"Filters -<br>requester: [[first] [last]]|[windows_id]<br>client: [[first] [last]]|[windows_id]<br>approver: [[first] [last]]|[windows_id]<br>worker: [[first] [last]]|[windows_id]<br>ticket: [id]<br>status: [open]|[closed]|[hold]<br>type: [termination]|[extension]|[access]|[password]|baskets]<br>item: [name for category/item/attribute inventory]<br>since: [mm/dd/yyyy]|[yyyy-mm-dd]<br>before: [mm/dd/yyyy]|[yyyy-mm-dd]<br>All searchs are AND with comma delimiting"|safe|tooltip}}
Or you can try removing esc from your tooltip tag.
Edit:
I just realized what you are trying to do. You cannot put html inside a tooltip in bootstrap, it's a plaintext feature only. data-html="true" allows it to contain html content. You can also use popover. Above safe filter should still be used in order to disable html escaping.
Turns out the problem was much stupider than what I thought it was - I had my <script> tags in the wrong order so I was getting the jQuery-UI tooltip instead of the Bootstrap tooltip, and the jQuery-UI tooltip doesn't support html.
Related
I need to include jinja templating in element.innerHTML but jinja is not working.
Code script.js:
contentDiv.innerHTML = getContent(fragmentId);
function getContent(fragmentId) {
var pages = {
quad1: `
<form class="form-inline" method="POST" id="form1">
<h3>
<input type="number" id="quad_a1" name="input_a" class="form-control mx-2 col-1" placeholder="a">
<b>x² +</b>
<input type="number" id="quad_b1" name="input_b" class="form-control mx-2 col-1" placeholder="b">
<b>x +</b>
<input type="number" name="input_c" class="form-control mx-2 col-1" placeholder="c">
<b>=</b>
<input type="number" name="input_d" class="form-control mx-2 col-2" placeholder="Default(0)">
<button type="submit" class="btn btn-primary float-right mr-5" onclick="return empty_quad()">Solve</button>
</h3>
</form>
{{ sol }}
`,
.
.
.
};
return pages[fragmentId];
}
But the output is literally {{ sol }}, not the value of sol:
So how to access the variable sol passed through flask's render_template() in script.js?
You can't use jinja2 template in your js file.
First method: You have to use inline javascript in html file using <script></script> tag, and then you can access the sol variable by assigning it to javascript variable
<script> sol = "{{sol}}" </script> // {{sol}} should be between quotation marks
Second method: If you have seperate js file. you can make a div tag, define it's class and set it's id to {{sol}}. get the element by class name and then get it's id.
Html
<div class="myclass" id="{{sol}}" style="display:none"></div>
javascript
elem= document.getElementsByClassName("myclass") ;
console.log(elem.id) // this is the sol value.
json_script
Safely outputs a Python object as JSON, wrapped in a <script> tag, ready for use with JavaScript.
Argument: HTML “id” of the <script> tag.
For example:
{{ value|json_script:"hello-data" }}
If value is the dictionary {'hello': 'world'}, the output will be:
<script id="hello-data" type="application/json">{"hello": "world"}</script>
The resulting data can be accessed in JavaScript like this:
const value = JSON.parse(document.getElementById('hello-data').textContent);
XSS attacks are mitigated by escaping the characters “<”, “>” and “&”. For example if value is {'hello': 'world</script>&'}, the output is:
<script id="hello-data" type="application/json">{"hello": "world\\u003C/script\\u003E\\u0026amp;"}</script>
This is compatible with a strict Content Security Policy that prohibits in-page script execution. It also maintains a clean separation between passive data and executable code.
django doc
I have this form which contains a button with some dynamic value, when I click on it it should add the product to the checkout page.
Here is the html form :
{%for p in product %}
<div class="single-product">
<div class="product-f-image">
<img src="data:image/png;base64,{{p.image_medium}}" alt="">
<div class="">
{% if not user.is_authenticated %}
<form action="/login/">
<button class="add-to-cart-link" type="submit"> Add to cart</button>
</form>
{%else%}
<form id="form-id" action="" method="POST">
{% csrf_token %}
<button class="add-to-cart-link" type="submit" name="product" value="{{p.id}}" >
<input type="hidden" name="product_name" value="{{p.name}}">
<input type="hidden" name="product_price" value="{{p.lst_price}}">
Add to cart</button>
</form>
{%endif%}
<i class="fa fa-link"></i> See details
</div>
</div>
<h2>{{p.id}}</h2>
<div class="product-carousel-price">
<ins>{{p.lst_price}} €</ins>
</div>
</div>
{%endfor%}
And here is my what I am doing with selenium:
bon_commande = self.selenium.find_element_by_xpath("//button[#name='product' and #value='37']/parent::form")
bon_commande.submit()
And thanks for the help !
You don't need to locate Submit button to submit a form - use any element inside form or form element itself:
self.selenium.find_element_by_id("form-id").submit()
self.selenium.find_element_by_class_name("add-to-cart-link").submit()
Update
Try to wait until django variable "{{p.id}}" is replaced with generated value:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(self.selenium, 10).until(EC.presence_of_element_located((By.XPATH, "//button[#name='product' and #value='37']"))).submit()
Change to click the submit button:
// add some sleep to wait the JS files of page
// load completely to register click event to the submit button
// otherwise nothing to response to the click
// (because the `action` of the form is empty.)
self.selenium.sleep(15); // sleep 15 seconds
self.selenium.find_element_by_xpath("//button[#name='product' and #value='37']").click()
To click on the button with text as Add to cart you can use the following line of code :
self.selenium.find_element_by_xpath("//form[#id='form-id']/button[#class='add-to-cart-link' and #name='product']").submit()
#or
self.selenium.find_element_by_xpath("//form[#id='form-id']/button[#class='add-to-cart-link' and #name='product']").click()
how to retrieve a form search parameters in a django generic listView. My url is:
url(r'postsearch$', views.PostsList.as_view(), name='postsearch'),
My generic listview is:
class PostsList(generic.ListView):
model = Post
template_name = 'posts/post_list.html'
def get_queryset(self):
localisation = #how to get location
discipline = #how to get discipline
return Post.objects.filter(.......)
and my form is:
<form class="form-inline text-center" action="{% url 'posts:postsearch' %}" id="form-searchLessons" method="get">
<div class="form-group">
<input type="text" class="form-control" id="typeCours" list="matieres" placeholder="Matieres: e.g. Math, Physique,.." name="discipline">
<datalist id="matieres">
<option value="value1">
<option value="value2">
</datalist>
</div>
<div class="form-group">
<input type="text" class="form-control" id="Localisation" placeholder="Lieu: Bousaada, Douaouda,.."
name="localisation" onFocus="geolocate()">
</div>
<button type="submit" class="btn btn-default" id="btn-getLessons">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span> Trouver !
</button>
</form>
I want to get the Posts by applying a filter according to the lacalisation and matieres introduced in the search fields (in the form)
You can add the search terms to your url regular expression.
url(r'postsearch/(?P<localisation>\w+)/(?P<descipline>\w+)/$', views.PostsList.as_view(), name='postsearch'),
(Note, mind the trailing slash)
In your get_queryset method you can use those given url parameters
def get_queryset(self):
localisation = self.kwargs['localisation'] or None
discipline = self.kwargs['discipline'] or None
filters = {}
if localisation:
filters.update(localisation: localisation)
if discipline:
filters.update(discipline: discipline)
return Post.objects.filter(**filters)
Eventually you should relocate getting the parameters outside your get_queryset, but that is up to you.
I'm not sure about the security risks doing it this way. Anyone having more information about the security risks during this operation, please share.
I build a library that can help you to solve this problem, you just have to put in the searchable_fields the attributes you want to filter and it will take care of the rest.
https://github.com/SchroterQuentin/django-search-listview
I'm looking for a way to not automatically show the CMS toolbar (version 3.3.0) when a 'staff-user' logs in.
The toolbar should only be activated when ?edit is in the URL.
The documentation mentions the CMS_TOOLBAR_HIDE option, but I don't see any effects when enabled. Also the description:
"If True, the toolbar is hidden in the pages out django CMS."
seems not totally clear to me...
Any ideas?
If you add ?toolbar_off to the URL the toolbar disappears completely (no toggle button). ?edit turns it back on.
To automatically turn it off:
(A) You'd could add something like a middleware or hook into the login chain and add the parameter there.
(B) You might subclass/extend the CMSToolbar to override the following default behavior:
def init_toolbar(self, request):
self.request = request
self.is_staff = self.request.user.is_staff
self.edit_mode = self.is_staff and self.request.session.get('cms_edit', False)
self.show_toolbar = self.is_staff or self.request.session.get('cms_edit', False)
if self.request.session.get('cms_toolbar_disabled', False):
self.show_toolbar = False
Especially the last lines would have to be changed to use a default of True:
if self.request.session.get('cms_toolbar_disabled', True):
self.show_toolbar = False
I have overridden the login.html and adding a trailing ?toolbar_off to the {{ next }} hidden input value.
<form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %}
<div class="form-element-wrapper">
<input class="form-input" type="text" name="username" autofocus="" maxlength="254"
required="" id="id_username" data-cip-id="id_username">
<span class="form-input-highlight"></span>
<span class="form-input-bar"></span>
<label for="username" class="form-label">Username</label>
</div>
<div class="form-element-wrapper">
<input class="form-input [% password_css %]" type="password" name="password" required=""
id="id_password" data-cip-id="id_password">
<span class="form-input-highlight"></span>
<span class="form-input-bar"></span>
<label for="password" class="form-label">Passwort</label>
<!-- THIS IS THE IMPORTANT LINE! -->
<input type="hidden" name="next" value="{{ next }}?toolbar_off"/>
</div>
<div class="form-element-wrapper">
<button class="form-element form-button" type="submit"
value="{% trans 'Log in' %}">{% trans 'Log in' %}</button>
</div>
</form>
Just a little solution if a user signs in via the login page. This does not affect the login via ?edit.
I have a form that is supposed to create a new 'Quote' record in Django. A 'Quote' requires a BookID for a foreign key.
This is my form
<form method="POST" action="{% url 'quotes:createQuote' %}">
{% csrf_token %}
<section>
<label for="q_text">Quote Text</label>
<input type="text" name="text" id="q_text" placeholder="Enter a Quote" style="padding-left:3px"> <br>
<label for="q_book">Book ID</label>
<input type="text" name="bookID" id="q_book" placeholder="Enter Book ID" style="padding-left:3px"> <br>
<label for="q_disp">Display Quote Now?</label>
<input type="radio" name="display" id="q_disp" value="True"> True
<input type="radio" name="display" value ="False">False <br>
<button value="submit">Submit</button>
</section>
</form>
And this is the method that it is targeting
def createQuote(request):
#b = get_object_or_404(Book, pk=request.bookID)
return HttpResponseRedirect(reverse('quotes:index'))
Somewhere in that request argument I assume there is some sort of field that contains the bookID the user will pass in on the form. How do I get at that information?
Bonus points for anyone who can tell me some way I can visualise data like I might with console.log(some.collection) in Javascript
if request.method == "POST":
book_id = request.POST['book_id']
Assuming you're sure it's in there. Otherwise you'll need to verify/provide a default value like you would for a normal python dictionary.
As for visualising the data, do you mean printing it to the console? In which case if you're running the django runserver you can just do print some_data. If you want it formatted a little nicer, you can use pretty print:
import pprint
pp = pprint.PrettyPrinter()
pp.pprint(some_data)