django render an object as html in a template - django

I am trying to render an object in a template like what we can do with forms {{ form }} but the output is turned into text and not html code. How to really include html code?
my_object = MyObject()
{{ my_object }}
The class:
from django.template import Context, Template
from django.utils.safestring import mark_safe
class MyObject(object):
def __str__(self):
return self.render()
def render(self):
t = Template('<p>This is your <span>{{ message }}</span>.</p>')
c = Context({'message': 'Your message'})
html = t.render(c)
return mark_safe(html)

You should be implementing __unicode__ instead of __str__. The templating module stringifies context variables as unicode.

You can also use
{% autoescape off %}
{{ info }}
{% endautoescape off %}
But you must be care to avoid xss vulnerabilities.

If the attempt is to get html on to the page then you should be using {{myobject|safe}}. That should render the HTML code instead of text

Related

Django Crispy forms input out of order

I am building some forms using django-crispy_forms, I need them to be in the some specific order (specifically the order I stablished on the fields inside forms.py).
forms.py:
class RegistroRelatorio(forms.ModelForm):
class Meta:
model = RelatorioVendas
fields = {"razao_social","codigo_interno","nome_fantasia","endereco","bairro","uf","telefones","cnpj","fundacao",
"negocios","cidades_negocios","c1_nome","c1_whats","c1_email","c1_cargo","c1_comunicacao","c1_preferencia"}
views.py
from django.shortcuts import render
from .models import RelatorioVendas
from django.http import HttpResponse
from .forms import RegistroRelatorio
# Create your views here.
def novo_relatorio(request):
form = RegistroRelatorio(request.POST or None)
if form.is_valid():
form.save()
return HttpResponse('Ok...')
return render(request,'river/novo_relatorio.html',{'form':form})
html:
{% extends 'river/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h3>Novo Relatorio</h3>
<form method="post" >
{% csrf_token %}
{{form | crispy}}
<button type="submit">Ok</button>
</form>
{% endblock %}
I tried to use label_order inside this class, it worked, but when I use the crispy form it stops working...
I even tried to use the Layout method from the crispy library.
Use a 'list' instead of a 'set' for the fields in forms.py:
class RegistroRelatorio(forms.ModelForm):
class Meta:
model = RelatorioVendas
fields = ["razao_social", "codigo_interno", "nome_fantasia", "endereco", "bairro", "uf", "telefones", "cnpj",
"fundacao", "negocios", "cidades_negocios", "c1_nome", "c1_whats", "c1_email", "c1_cargo",
"c1_comunicacao", "c1_preferencia"]
According to the documentation:
A set is an unordered collection with no duplicate elements.
I don't see any problems here for crispy to render fields in the order that you provided. Show your html and views.

How to replace placeholders in placeholders (variables) in Django?

In a Django template, I'd like to add text from a model field. This text field can be understood as text-template itself. It may look like:
Dear {{user}},
thank your for...
Regards,
{{sender}}
This text field is available as emailtemplate inside a normal Django template. The fields from above (user=Joe, sender=Alice) are available as well.
{% extends 'base.html' %}
{% block content %}
{{ emailtemplate }}
{% endblock %}
The output shall be as follows
Dear Joe,
thank your for...
Regards,
Alice
I have no clue how to do this with built-in methods. My only idea is to parse emailtemplate manually before I hand it over to the template engine, thus inside the view. But I'm sure, I'm not the first one with that problem.
After several reworks, I came up with the following solution. Double check who can modify/alter the template string since this could be a big security flaw, if alterable by the wrong people.
views.py:
class YourView(TemplateView):
template_name = 'page.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["emailtemplate"] = "Dear {{user}}, {{sender}}"
context["user"] = "Joe"
context["sender"] = "Alice"
return context
page.html:
{% extends 'base.html' %}
{% load core_tags %}
{% block content %}
{% foobar emailtemplate %}
{% endblock %}
your_app/templatetags/core_tags.py (don't forget the __init__.py file to ensure the directory is treated as a Python package your_app must also be in INSTALLED_APPS):
from django import template
from django.template import Template
register = template.Library()
#register.simple_tag(takes_context=True)
def foobar(context, ts):
t = Template(template_string=ts)
return t.render(context)
See also:
https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/#code-layout
https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/#simple-tags

DatePickerWidget with Flask, Flask-Admin and WTforms

I'm trying to render a template that contains a DatePicker, but I'm getting a 500 error when I try. For my the code is correct, but it seems that something is failing or I'm not understanding correctly the way to do it.
The code is the following:
Reporting.py
from flask.ext.admin import BaseView, expose
from wtforms import DateField, Form
from wtforms.validators import Required
from flask.ext.admin.form import widgets
from flask import request
class DateRangeForm(Form):
start_date = DateField('Start', validators=[Required()], format = '%d/%m/%Y', description = 'Time that the event will occur', widget=widgets.DatePickerWidget)
class ReportingView(BaseView):
#expose('/')
def index(self):
form = DateRangeForm(request.form)
return self.render('reporting.j2', form=form)
Reporting template:
{% extends 'admin/master.html' %}
{% block body %}
{{super()}}
Working on it!
{% if form %}
{{form.start_date}}
{% endif %}
{% endblock %}
As davidism says in the comments, the default DateField just provides date parsing, it'll just be displayed as a normal text-input.
If you're ready to fully embrace html5 then you can use the DateField from wtforms.fields.html5 which will render a datepicker in any browser that supports it:
from flask import Flask, render_template
from flask_wtf import Form
from wtforms.fields.html5 import DateField
app = Flask(__name__)
app.secret_key = 'SHH!'
class ExampleForm(Form):
dt = DateField('DatePicker', format='%Y-%m-%d')
#app.route('/', methods=['POST','GET'])
def hello_world():
form = ExampleForm()
if form.validate_on_submit():
return form.dt.data.strftime('%Y-%m-%d')
return render_template('example.html', form=form)
if __name__ == '__main__':
app.run(debug=True)
The more usual approach is to find a nice datepicker online, that's using CSS and JS to handle it's display and include that code into your html template, and tell it to apply the datepicker style to any html element that has a class of datepicker. Then when you generate your form you can just do:
<!-- all your CSS and JS code, including the stuff -->
<!-- to handle the datepicker formatting -->
<form action="#" method="post">
{{ form.dt(class='datepicker') }}
{{ form.hidden_tag() }}
<input type="submit"/>
</form>
Any attributes (that aren't reserved for other use) you pass into rendering the form element will by default just add it as an attribute, for example the {{ form.dt(class='datepicker') }} will generate <input class="datepicker" id="dt" name="dt" type="text" value=""> so your CSS/JS can then do whatever it needs to do to provide a good interface for your user.

Include template as verbatim

I have a template which I'm inserting with include tag:
{% include 'template.html' %}
Also in another place I want its contents to be displayed as raw. How can I achieve this?
You can try something like:
page1.html
{%with flag="norender" %}
{% include "template.html" %}
{%endwith%}
template.html
{%if flag == "norender" %}
{%verbatim%}
{%endif%}
{#your html #}
{%if flag == "norender" %}
{%endverbatim%}
{%endif%}
I ended up creating a template tag to do this:
from django import template
from django.template.loader import get_template
from django.utils.html import escape
register = template.Library()
#register.simple_tag()
def verbatim_include(name):
"""
Example: {% verbatim_include "weblog/post.html" %}
"""
template = get_template(name)
return escape(template.render())
I've no idea if it's the best or most efficient method, but it seems to work OK for me (Django 1.11).
In my main template I'll include another like this:
<pre><code>{% verbatim_include 'my_template.html' %}</code></pre>
And if my_template.html is like this:
<b>This is my template</b>
Then in the browser I'll see:
<b>This is my template</b>
And not:
This is my template
Tested on Django 1.11:
from django import template
from django.template.loader import get_template
from django.utils.safestring import mark_safe
register = template.Library()
#register.simple_tag
def verbatim_include(name):
"""
Example: {% verbatim_include "weblog/post.html" %}
"""
template = get_template(name)
source = template.template.source
return mark_safe(source)

Rendering a template variable as HTML

I use the 'messages' interface to pass messages to user like this:
request.user.message_set.create(message=message)
I would like to include html in my {{ message }} variable and render it without escaping the markup in the template.
If you don't want the HTML to be escaped, look at the safe filter and the autoescape tag:
safe:
{{ myhtml |safe }}
autoescape:
{% autoescape off %}
{{ myhtml }}
{% endautoescape %}
If you want to do something more complicated with your text you could create your own filter and do some magic before returning the html.
With a templatag file looking like this:
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
#register.filter
def do_something(title, content):
something = '<h1>%s</h1><p>%s</p>' % (title, content)
return mark_safe(something)
Then you could add this in your template file
<body>
...
{{ title|do_something:content }}
...
</body>
And this would give you a nice outcome.
Use the autoescape to turn HTML escaping off:
{% autoescape off %}{{ message }}{% endautoescape %}
You can render a template in your code like so:
from django.template import Context, Template
t = Template('This is your <span>{{ message }}</span>.')
c = Context({'message': 'Your message'})
html = t.render(c)
See the Django docs for further information.
The simplest way is to use the safe filter:
{{ message|safe }}
Check out the Django documentation for the safe filter for more information.
No need to use the filter or tag in template.
Just use format_html() to translate variable to html and Django will automatically turn escape off for you variable.
format_html("<h1>Hello</h1>")
Check out here https://docs.djangoproject.com/en/3.0/ref/utils/#django.utils.html.format_html
The safe filter did the work for me.
Using {{data|safe}} includes the html as it is.