django dynamic inclusion tag - django

I'm trying to add some image gallery to the template but position of the gallery on the page need to be defined by user. Sometimes it will be at the top of the text, sometimes at the end and sometimes at the middle of the text on the page. In the text field user will add this line #foto and based on the position of the that line I need to render gallery. For example:
some paragraph written by user in the text field...
#foto
some another paragraph written by user ...
Now the easiest way will be to replace #foto with include tag in the view. Something as :
foto = "{% include 'includes/gallery.html' %}"
xx = "#foto"
post.text = post.text.replace(xx, foto)
But this example doesn't work because include tag can't be call on that way. It is rendered as pure text {% include 'includes/gallery.html' %}. What can be done to render include tag as expected on the position of the #foto text.

assign foto the rendered template, inside your view:
...
from django.template.loader import render_to_string
"""
Get the items from the model, define your query
"""
gallery = GalleryModel.objects.all()
"""
Render gallery template and assign to foto, which then you
can inject in the basic template
"""
foto = render_to_string('includes/gallery.html', {'gallery': gallery})
...
then in your template:
{{ foto }}

Related

How to add Wagtail 'admin' menu to custom templates?

On templates that derive from the Wagtail Page model, there is a small Wagtail icon/menu in the lower right corner. This provides a quick way to edit the page and/or jump to the Wagtail Admin. However, this menu does not appear on custom view templates that are not derived from Wagtail Page model.
How can I tell Wagtail to display the small menu on my frontend templates, so the pages have consistent navigation?
The standard Wagtail user bar is rendered by placing in your template:
{% load wagtailuserbar %}
{% wagtailuserbar 'top-left' %}
I typically just put the above in base.html. The 'top-left' designation, of course, tells the template tag where to render the user bar. Reference
However, the wagtailuserbar is only rendered for Wagtail pages. What you want to do is render the user bar with only the Go to Wagtail Admin option (because no other options would be relevant). Therefore, you could create your own template tag and place it in base.html beside the wagtailuserbar. You would set it up so that it renders if there IS NO page in the context (the wagtailuserbar template tag checks to make sure there IS a page in the context). To create your tag, just start with the code from wagtailuserbar.py and modify it to create a template tag called wagtailuserbar_admin_only (untested):
from django import template
from django.template.loader import render_to_string
from wagtail.admin.templatetags.wagtailuserbar import get_page_instance
from wagtail.admin.userbar import (AdminItem)
#register.simple_tag(takes_context=True)
def wagtailuserbar_admin_only(context, position='bottom-right'):
# Find request object
try:
request = context['request']
except KeyError:
return ''
# Don't render without a user because we can't check their permissions
try:
user = request.user
except AttributeError:
return ''
# Don't render if user doesn't have permission to access the admin area
if not user.has_perm('wagtailadmin.access_admin'):
return ''
# Only render if the context does NOT contain a variable referencing a saved page
page = get_page_instance(context)
if page:
return ''
# Render the items
rendered_items = [AdminItem()]
# Render the userbar items
return render_to_string('wagtailadmin/userbar/base.html', {
'request': request,
'items': rendered_items,
'position': position,
})
Then, to use in templates, place in base.html:
{% load wagtailuserbar_admin_only %}
{% wagtailuserbar_admin_only 'top-left' %}

How do I use static files in a Django model's TextField?

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.

How to process django url tags in context variables

I'm creating a django-based website where page content is stored in a model textfield with a detail view of the model displaying it. How can I put {% url %} tags in the content to link to other pages without hard coding links?
Putting the tag into the textfield will just print the tag as plain text. (or if inside an href create a broken link)
Other options are
parsing the content manually inside the view and replacing the tags with the correct url
using some django supplied string parser to create the links before sending to the template
maybe there is a way to do it in the template with a filter or tag around the variable.
I could probably do the manual way but I am hoping there is a django way that I am missing.
class Page(models.Model):
content = models.TextField(blank=True)
class PageView(DetailView):
model=Page
context_object_name='page'
{% extends "base.html" %}
{% block content %}
{{ page.content|safe }}
{% endblock %}
Edit for clarity:
Content in admin
What it renders
What it should render
Edit 2:
I was able to find a solution to the second option thanks to this answer on another question. Using that template_from_string function I rendered the page content as a template then replaced the content in the context with the rendered result.
class PageView(DetailView):
model=Page
context_object_name='page'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Add to context here
context['page'].content = template_from_string(context['page'].content).render(context)
return context
your url's will have a name as shown below-
path('page//',PageView.as_view, name="page-detail")
and in your Page Detail
hope this is what your asking for
Let see if I understood you well, do you want django to show you a url as such and not as plain text?
If you want to avoid django to show you the data as plain text, you can use the escape filter as follows: {{string | escape}}
Check this page for more details about django filters and tags

Django render template variable

I have a field called "GOALS" that is rendered as a template variable and stored in a django model. That field is input via the admin interface and contains raw html, so in the django template there is
<html>
...
<P>{{ GOALS|safe }}</P}
...
</html>
Now I want to render this variable before it gets placed into context with my own template tag. This will allow staff to enter tags that will query the database rather than hard code variables such as the title of a project that is identified by a slug etc.
I thought of allowing them to enter template tags such as
GOALS = "... {{ "slug"|gettitle }} ..."
and rendering GOALS before it entered the context with
from django.template import Template, Context
html2render = "{% load episode_tags %}" + GOALS
miniTemplate = Template(html2render)
context = Context({})
GOALS = miniTemplate.render(context)
but loading my template tags did not work using Template this way, and this crashed with TemplateSyntaxError. So I figured I could use ElementTree and XML, but before I go ahead and do that (which is a little tedious) I wanted to ask the wider community if there was some better way to do this.
As it turned out, the solution I proposed was correct (thanks #GwynBleidD). The editor in django admin that allowed entry of the fields used widget CKEditorWidget that automatically renders the html. It was turning quotes " into ". I started subclassing the widget to replace the html safe quotes, but I just don't have the time. I told the user to expect to see the " in the source and used the following.
# The GOALS field is rendered by the CKEditorWidget before it is stored.
html2render = "{% load episode_tags %}" + GOALS.replace(""", '"')
try:
miniTemplate = Template(html2render)
context = Context({})
GOALS = miniTemplate.render(context)
except TemplateSyntaxError:
pass

Minimal Url and view for static pages on django

The app I am creating has many static pages, just like the pages of a website which do not change for some time. Im my model I will have a title field and a text field. I am looking go a way to avoid multiple views and multiple urls for each page. I tried using flatpages, but I was not able to get to work the context processors. For example, if a certain page has many grids. So how to write a single view and a url which will deliver all the pages, along with the context processors.
If you are having problems with flatpages, it's not hard to write your own version!
models.py
from markdown import markdown
class CustomFlatPage(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
slug = models.SlugField(unique=True)
urls.py
url(r'^(?P<slug>[-\w]+)/$','myapp.views.customflatpage', name='customflatpage'),
views.py
from django.views.generic.simple import direct_to_template
def customflatpage(request,slug):
page = get_object_or_404(CustomFlatPage, slug=slug)
return direct_to_template('path/flatpage_template.html',
extra_context={
"page":page,
})
template (has access to request context etc.)
{{ page.title}}
{{ load markup }}
{{ page.body|markdown }}
Use TinyMCE on the body field in django-admin (if you are using it) or your own form if you want rich text.