I need to display static content inside of a model's TextField.
I have tried marking the TextField as safe in the template, but it doesn't seem to interpret it like the rest of the the template tags, only displaying it as raw HTML.
From my template:
{{ project.content|safe }}
From my model:
content = models.TextField()
From my view:
class ProjectView(generic.DetailView):
model = Project
context_object_name = "project"
template_name = "projects/project.html"
I'm expecting the content ({% static "wdv101/koala/index.html" %}) to display as a url to the static content, but instead it displays as {% static "wdv101/koala/index.html" %}
What you are trying to achieve is to use the string or project.content as template. Marking it as save means that e.g. Javascript is not escaped so that i will be executed.
You could solve your "problem" with a custom template tag that takes your content variable as input, renders it and returns the rendered html.
Custom template tag:
from django import template
from django.template import Template
from django.utils.html import mark_safe
register = template.Library()
#register.simple_tag(takes_context=True)
def in_template_renderer(context, template_string):
template = Template(template_string)
return mark_safe(template.render(context))
Using it in the template:
{% load in_template_renderer %}
{% in_template_renderer project.content %}
Do not forget to load required modules such as 'static' in your project.content.
Related
I'm using {% autoescape off %} to render html that I add through admin page. I want to get another variable of the model.
post.html
{% autoescape off %}
{{ post.content }}
{% endautoescape %}
Is it possible to pass another attribute of the same model into post.content? Something like that
post.content
<img src="{{ post.main_image.url }}">
Yup. Assuming there is a post, and it has a main_image, which has a url, there shouldn't be any problem. You may want to check in the template if you are not sure yourself first though. So to be safer, you should do:
{% if post and post.main_image %}
<img src="{{ post.main_image.url }}">
{% endif %}
Ok, I've finally made it. My goal was to create CMS-ish admin page of a model, where I could add raw html, django tags and variables directly to the content attribute along with other attributes like titles, categories, images and so on. I've managed to do it by using and customizing django-dbtemplates package.
pip install django-dbtemplates
First, fork template model from dbtemplates and add your model as a foreign key
blog/models.py
from dbtemplates.models import Template as CoreTemplate
class Template(CoreTemplate):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
Then just customize your admin.py to show template field as an attribute
blog/admin.py
from .models import Post, Template
class TemplateInline(admin.TabularInline):
model = Template
extra = 0
class PostAdmin(admin.ModelAdmin):
inlines = [TemplateInline, ]
Optional
You can generate html names of you template based on your model slug by modifying save function of the Template class
blog/models.py
from dbtemplates.models import Template as CoreTemplate
from dbtemplates.conf import settings
class Template(CoreTemplate):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
def save(self, *args, **kwargs):
self.last_changed = now()
slug = self.post.slug
self.name = f'{slug}-content.html'
if settings.DBTEMPLATES_AUTO_POPULATE_CONTENT and not self.content:
self.populate()
super(Template, self).save(*args, **kwargs)
Then in your html you can render this template with context manager
post.html
{% with post.slug|add:'-content.html' as content %}
{% include content %}
{% endwith %}
Now in your admin settings you can have just one big content field from basic Template class
blog/admin.py
from .models import Template
from django.forms import Textarea
class TemplateInline(admin.TabularInline):
model = Template
extra = 0
fields = ('content',)
formfield_overrides = {
models.TextField: {'widget': Textarea(attrs={'rows': 40, 'cols': 150})},
}
To remove default dbtemplates Template class from your admin panel just unregister it in your admin settings
blog/admin.py
from dbtemplates.admin import Template as CoreTemplate
admin.site.unregister(CoreTemplate)
I have an HTML page with a link to redirect to another HTML template which has a form. I have used the class based view in rendering it. But it simply does not load.
My views.py look something like :
def startup(request):
return render(request, 'main/startup.html')
class AddStartup(CreateView):
model = Startup
template_name = 'startup_form.html'
fields = ['startup_name', 'startup_product', 'startup_date', 'startup_sector', 'startup_team_size',
'startup_desc', 'startup_team_condition', 'startup_team']
urls.py
# I have posted only the relevant code
url(r'startup/$', views.startup, name = 'startup'),
url(r'startup/add-startup/$', views.AddStartup.as_view(), name = 'add-startup'),
My HTML page which has a link to navigate to the field is below
{% extends "main/base.html" %}
{%block content%}
pass<br>
<a
href = "{%url "main:add-startup"%}" target="_parent" method = "post">
Add Startup
</a>
{%endblock%}
I am a bit confused in Class based views so that is why I choose to mix them. Help would be appriciated
I have this data that comes from a field in the database:
item_list = Links.objects.filter(visible=True)
In an iteration of item_list there is item.name and item.link. In item.link there could potentially be a string value of
'/app/user/{{user.id}}/'.
When rendering this particular item.link in a Django template, it comes out literally in html output as:
/app/user/{{user.id}}/
when literally I am hoping for it to render as:
/app/user/1/
Is there any way to force the template to recognize this as a compiled value for output?
You have to create a custom template tag:
from django import template
register = template.Library()
#register.simple_tag(takes_context=True)
def render(context, tpl_string):
t = template.Template(tpl_string)
return t.render(context)
And the in your template:
{% load my_tags %}
{% render item.link %}
I need to add to the output of the TemplateView html {%extends some_base.html%} in the views.py.
I can't work with html directly, cause template_name will be always different and i don't want to add {%extends..%} to each template.html file.
i want to do something like this:
class PageView(TemplateView):
def get_context_data(self, **kwargs):
object = PageModel.objects.get(view_base__slug=kwargs.get('slug'))
self.template_name = object.template_name
self.base='base.html'
from django.template.loader import render_to_string
#just example, it's not working
rendered = render_to_string(self.template_name)
rendered= '{% extends' + self.base + '%} '+ rendered
###
return locals()
But it does not work. Even more - i want to save all variables, which are being passed to the template.
I'm not sure why are you trying but you cannot put {%extends ...%} in HTML (unless you want to render it again using django templates. Adding that string to template after rendering will add unwanted {%extends ...%} string in the template.
But if you want you can create a template dynamically and render it. The new template can extend existing template.
For example:
>>> from django.template import Template, Context
>>> #creates a template from string, "base.html" can be self.base in your case
>>> t = Template('{%extends "' + "base.html" + '"%} ...')
>>> c = Context({'your_var1': 'var1_value'}) #get context for template
>>> t.render(c) #render the created template
u'\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n
<html xmlns="http://www.w3.org/1999/xhtml">
....
More reference at: Template Compiling a string
The same you can achieve in django template by passing a variable template_name to template. And then in template put this code at very top.
{% with template_name|add:".html" as template %}
{% include template %}
{% endwith %}
Or see this question for more help.
I'm trying to use WTForms with Django & a MongoEngine/MongoDB database backend. The forms are outputting properly, but I can't for the life of me get the labels to show up.
Here is my template code:
{% load wtforms %}
<form>
{% for f in form %}
{{ f.label }}: {% form_field f %}<br/>
{% endfor %}
</form>
This is what I am passing in the view:
form = StrandForm()
return render_to_response('create_strand.html', locals(), context_instance = RequestContext(request))
The StrandForm class I have tried both creating from the WTForm mongoengine extension's model_form class, and from WTForm's Form class. The label exists in the view, I can print it to the console and it shows the rendered form label, but somehow it gets lost when transferring to the template. Am I doing something wrong?
Django 1.4 has a new feature: do_not_call_in_templates attribute.
If you set it on wtforms.Field class, every child class inherits and all fields will work fine in django templates.
import wtforms
wtforms.Field.do_not_call_in_templates = True
Now following code works as expected:
{% load wtforms %}
{{ f.label }}: {% form_field f %}
I encountered the same problem today. It has to do with the way WTForms is programmed so that it will work with many different templating libraries. Django 1.3 will only see f as it's HTML string even though it has other attributes.
In order to fix this you must add a template tag to retrieve the attribute.
Add the following to your projects hierarchy:
templatetags
templatetags / init.py
templatetags / templatetags
templatetags / templatetags / init.py
templatetags / templatetags / getattribute.py
Then in your settings.py file, add the following line to INSTALLED_APPS
'templatetags',
Open up getattribute.py and paste the following code:
from django import template
from django.conf import settings
register = template.Library()
#register.tag
def getattribute(parser, token):
try:
tag_name, tag_object, tag_function = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError("%r tag requires two arguments" % token.contents.split()[0])
return getattrNode(tag_object, tag_function)
class getattrNode(template.Node):
def __init__(self, tag_object, tag_function):
self.tag_object = tag_object
self.tag_function = tag_function
def render(self, context):
return getattr(context[self.tag_object], self.tag_function)()
This will allow you to use the follow code whenever you're inside a template and need an attribute that won't show up:
{% load getattribute %}
{% getattribute OBJECT ATTRIBUTE %}
In your case:
{% getattribute f label %}
Hope that helped!