How do I dynamically use include in a Flask Template? - templates

I have a flask backend sending data to the client. Some JS on the client side then utilizes that data to construct a page that includes one row of data and another area below the row that has a d3 display with clickable nodes.
The nodes have different properties corresponding to different models in the backend and different html templates. Given a type, when clicked, a different html template is presented in the row above.
How do I set the template from the JS? I tried doing something like:
$("#div_id").innerHTML = "{% set obj = " + obj + "%}{% include '" + obj_template_file + "' %}"
That (perhaps of course) didn't work. After taking care of escaping, it just displays that string. I thought of dirty ways of doing this like using hide and show liberally but that doesn't seem wise.

ALthough is not clear what you mean by "sending data to the client".
You can pass the base_template argument from your routes like:
#auth.route('/<path:path>', methods=['GET', 'POST'])
def password_reset_request():
if path ==2:
base_template = "jay.html"
if path ==3:
base_template = "blue.html"
...
return render_template('auth/reset_password.html', base_template=base_template)
and on the template:
{% extends base_template %}
THen from your javascript frontend you just need to GET the URL.

Related

Detect URLs and #tags in Django CharField and add style to it

For now on I have in my template a paragraph like this <p class="...">{{ post.content }}</p> and if this Post's content contains a link or #hashtag it is rendered as a normal text with the rest of the post. How can I customize it? For example change text-color and add tag around it?
As I said in comment, you can use custom tag filter to wrap your content, and use Regular Expression to generate links and hashtags
Create your tags file, and name it as you want:
tag_filter_name.py
If you're not familiar with custom tag filter creation, you can learn more about it in the Official Documentation
from django import template
import re
register = template.Library()
def generate_link(link):
return '<a class="link" href="{}">{}</a>'.format(link, link)
def generate_hashtag_link(tag):
# Free to configuree the URL the way adapted your project
url = "/tags/{}/".format(tag)
return '<a class="hashtag" href="{}">#{}</a>'.format(url, tag)
And then, you create the function what will be used as tag filter
#register.filter
def render_content(obj):
text = re.sub(r"#(\w+)", lambda m: generate_hashtag_link(m.group(1)),obj)
return re.sub(r"(?P<url>https?://[^\s]+)", lambda m: generate_link(m.group(1)),text)
If you want Django to mark it as safe content, you can do the following:
from django.utils.safestring import mark_safe # import function
''' function codes here '''
return mark_safe(re.sub(r"(?Phttps?://[^\s]+)",
lambda m: generate_link(m.group(1)),text))
And finally, to use it in your template, don't forget to load it
{% load tag_filter_name %}
{{ post.content|render_content }}
Best way: custom tag filters here is the docs URL
https://docs.djangoproject.com/en/2.2/ref/templates/builtins/
Good way: If you know JS create a function that handles the formatting on the front end
in HTML:
onload="myfunction("{{post.content}}")"
in JS sort for the string containing the # wrap it in a span or other element and style away. then replace the inner HTML with your new formatted piece. This will save rendering time on the server and also frees you up from having to loop thru the list of posts in the view
Ok way: not preferred but if you hate js and only want to work in python (understandable). You need to loop through the list of posts separate out the items of the post format them the way you like with inline style. then add them to a new object that you will append to the end of a new list of posts that you will then pass thru to context. This is a real pain please don't do this if you can help it at all.
the tag filters are awsome take advantage but if they won't work for your use case I would highly advise using vanilla JS

Passing HTML code as string variable to template for PDF generation

I'm working on a Django app which parses xlsx input, processes series of REST API queries and returns the result of the queries as a table in one of my django templates. The HTML code containing the results table is generated with Pandas.to_html() functionality. The HTML code is stored in a variable ("table") and passed to the html template, where it is displayed as {{ table | safe }}. This mechanism works just fine. However, I'm now struggling to add a button which would generate a pdf file to be downloaded by the user.
NOTE: I'm aware it would probably make more sense to use JS to render the PDF on the client side, but at the moment the point is to avoid doing so.
Upon some research, I decided to go with the django-easy-pdf library. I based my solution on the example included in the documentation, but so far to no avail.
In urls.py:
urlpatterns = [
[...]
path('result.pdf', views.PDFView.as_view(), name='PDFview'),
]
In views.py:
class PDFView(PDFTemplateView):
template_name = 'whitelist/listresult.html'
table = None
def get_context_data(self, **kwargs):
return super(PDFView, self).get_context_data(pagesize='A4', title='Hi there!', table=self.table, date=date.today)
Please note that the template "listresult.html" is the one expecting the {{ table }} variable.
Last but not least, in the very listresult.html (where I want to place the button to render the PDF file), I added a simple button object:
<a class="btn btn-secondary btn-lg" href="{% url 'PDFview' table %}">Download PDF</a>
My expectation was that since I'm sending the "table" variable along with the request for PDF url, the view would process it nicely and prompt the user with a download pop-up for the PDF file looking exactly (or almost exactly) as the page which presented the result in the first place. However, I'm cought in a vicious circle where if I add "table" to the url reference on the site I get an error during template rendering for the very website displaying results (NoReverseMatch for ..., Reverse for 'PDFview' with arguments '['table' contents go here] not found). On the other hand, if I remove the "table" argument from the url reference, the results website renders OK with the "Download PDF" button, but upon clicking it I'm left with a Runtime Error (since context is missing).
I'm 97% confident my mistake is ostentatiously stupid, but after x hours of struggle I'm ready for StackOverflow's judgement.

django dynamic javascript in custom widget

I have a javascript code in rendered html page of custom widget. I want to move the js code to separate js file.
However, it must be dynamic not static media file.
I wrote a custom widget:
class CustomWidget(CustomWidgetBase):
css = {
'all': (
config['custom_css'] +
config['extra_css']
)
}
js = (
config['custom_js'] +
config['extra_js']
)
#property
def media(self):
media = super(CustomWidget, self).media
media.add_css(CustomWidget.css)
media.add_js(CustomWidget.js)
return media
def render(self, name, value, attrs=None):
attrs_for_textarea = attrs.copy()
attrs_for_textarea['hidden'] = 'true'
attrs_for_textarea['id'] += '-textarea'
html = super(CustomWidget, self).render(name, value, attrs_for_textarea)
html += render_to_string(
'app/custom_widget.html',
{
'id': attrs['id'].replace('-', '_'),
'id_src': attrs['id'],
'value': value if value else '',
'settings': json.dumps(self.template_contexts()),
'STATIC_URL': settings.STATIC_URL,
'CSRF_COOKIE_NAME': settings.CSRF_COOKIE_NAME,
}
)
CustomWidget.js += (os.path.join(settings.STATIC_URL, 'app/my.js'),)
return mark_safe(html)
'app/custom_widget.html' has javascript code:
{% load staticfiles %}
<div id='{{ id_src }}'>{{ value|safe }}</div>
<script>
$(function() {
var {{ id }}_textarea = window.document.getElementById('{{ id_src }}-textarea');
... omitted ...
I'd like to move javascript code in 'app/custom_widget.html' into 'app/my.js' because it makes widget code dependent on the order of javascript declarations.
Thus, 'app/my.js' must be dynamically generated with the values passed by Django view. I want to place 'app/my.js' at the bottom of the page.
Thank you.
Two options:
You can put a list of variable declarations in a script tag in your template, making sure they're declared before you import your static javascript. Then your static javascript refers to variable values that it knows were appropriately set by the server.
Put your dynamic values in data attributes in your HTML elements. Then write your static javascript to look up the appropriate server-set data based on what it's manipulating.
What you’re doing in your sample code looks very complex and I’m not sure it needs to be. If I interpret correctly, you are trying to make sure that when you insert a custom widget, a custom javascript behaviour will be applied to it.
I think the second option is more appropriate for that behaviour and that you should probably use jquery to make it as simple to implement as possible.
Firstly, in your custom widget’s html template, give your custom widget a class that lets your javascript know to apply custom behaviours to it.
eg,
<input class=“custom-behaviour-widget” data-id_name=“{{ id }}" data-other_variable_name=“other_variable-value" …>
Then write static javascript that looks like:
<script>
$( document ).ready(function () {
$(‘.custom-behaviour-widget’).each(
value_that_i_want = $(this).data(‘id_name’);
...
);
});
</script>

django url parse formatted url

I'm in the design stages of a single page web app, and would like to make it so that a user can click on a formatted URL and the data requests will load in the page.
For example, a url of http://www.mysite.com/?category=some_cat will trigger the Category view with the relevant data.
My intention is to parse the URL, gather the data, then pass it to the index.html template for rendering on page load. Once the page has been loaded, a Javascript trigger setting will trigger the appropriate button to load the client view.
However, I'm having an issue setting up the URL parser, as the following settings are not matching the example url above.
from app.views import app_views, photo_views, user_views, admin_views
urlpatterns = patterns("",
url(r'^/(?P<category>\d+)/$', app_views.index)
)
You're confusing between sending information through your urls with GET and formatting you urls with arguments for the view functions. Say I am visiting a site called http://www.mysite.com/ and the page has a form that looks like this:
<form>
<input type='text' name='category' id='category'></input>
<button type='submit'>Send!</button>
</form>
upon clicking, the url will automatically change to http://www.mysite.com/?category=<value of input>. The ? marks that everything afterwards should be treated as GET data, with the syntax of <id>=<value>. You can then access them like so:
def response(request):
category = request.GET['category']
formatting urls is different, because it means looking for patterns that are part of the url. i.e. a pattern that looks like r'^/(?P<category>\d+)/$' will look for this: http://www.mysite.com/<category>/ and it will send it to the request in your views as an additional argument like so:
def response(request, category):
...
The regex is used to define how you recognize that part of the url. For example, the \d+ you're using means that category needs to be a number. You can search how to define different types of patterns according to your needs
Note that with GET you are sending the data to the same view function that rendered the page you are currently visiting, while using a different url means you tell it where to go through your urls.py (usually a different function). Does that make things a bit clearer?

What is the right and efficient way of displaying images based on name in Django

I'm really new to Django. I'm having difficulty displaying images based on their name and according to the url pattern.
So basically the url consists of several variables within them and I want to be able to use that to fetch a particular image that is named with those variables.
Example:
localhost:8080/farm/chicken
this would fetch an image inside of my ../static/images/ folder and get:
farm_chicken.jpg
Another example:
localhost:8080/zoo/alligator
would get:
zoo_alligator.jpg
I can fetch the url parameters. So, should I make these image names within my views.py file and pass the names (zoo_alligator) into a context to be retrieved by the template later on? Would this be the correct way?
Thank you for your advice everybody! I appreciate all the help!
You won't actually do something like that, in general. What you should do is to send the image as a context variable from your view function to your template.
If you are using your url node to determine which picture to show, then in your corresponding view function, you are actually using "alligator" or "chicken" to load up the corresponding Animal class.
Once the correct animal object is instantiated, you could send this animal object to your django template and load in the image using a snippet similar to this:-
Like this:-
{% if animal.get_latest_medium_url %}
<img id="animal_image" class="img-rounded left" src="/media/{{ animal_image }}" />
{% endif %}
The get_latest_medium_url is a method in my Merchant class and it computes the url there.
So, should I make these image names within my views.py file and pass
the names (zoo_alligator) into a context to be retrieved by the
template later on? Would this be the correct way?
Sure, this is one way to do it. Something like this:
(r'show/(?P<in_path>.*)$','someapp.image_view')
Then in image_view:
def image_view(request,in_path):
img = in_path.replace('/','_')+'.jpg'
return render(request,'some_template.html',{'path':img})
However, as your view is very simple - you can pass the path directly to the template from urls.py, using direct_to_template:
from django.views.generic.simple import direct_to_template
(r'show/(?P<in_path>.*)$',direct_to_template,{'template':'some_template.html'})
In some_template.html:
<img src="{{ params.in_path }}">
The problem is that you won't get your string formatting done as the default filters do not have a "replace" function. You can easily write a custom filter:
#register.filter
#stringfilter
def format_path(the_path):
return the_path.replace('/','_')+'.jpg'
Then modify the template:
<img src="{{ params.in_path|format_path }}">
You should read the documentation on writing custom filters and tags for more details including where to store the filter code to make sure django can find it.