Dmitry Torba
Dmitry Torba

Reputation: 3194

Including the same blocks in several pages in Django

On my website, blog posts appear in multiple places across the site. I want to create a template like blog_posts.html that given the list of blog posts (as an argument to render) creates the block with these posts, formatted and processed.

There are several disconnected pages to which I want to display blog_posts. Thus, I can not say that blog_posts extend any of them. I wonder if there is a way to insert whatever template processed to arbitrary page? If yes, how to I pass variables (which may be instances of the classes) to the blog_posts template?

Upvotes: 0

Views: 214

Answers (2)

davidejones
davidejones

Reputation: 1949

you might want to consider using template tags. Something like the inclusion tag should serve you well (see here for docs https://docs.djangoproject.com/en/1.10/howto/custom-template-tags/#inclusion-tags)

You could use the takes_context argument to pass the data. So that any page you want to use the inclusion tag on you could already populate that page with a context variable of 'data' in the view then this function would pickup on it like this

@register.inclusion_tag('/path/to/blog_posts.html', takes_context=True)
def blog_posts(context):
    return {
        'blog_posts': context['data'],
    }

Then usage in you html file you want to pull blog posts into

{% blog_posts %}

Usage from any views. make sure you set data anywhere you want to also use the template tag

def example_view(request):
    context = {'data': Blog.objects.all()}
    return render(request, 'example.html', context)

Another option is to explicitly pass it in as an argument like this

@register.inclusion_tag('/path/to/blog_posts.html')
    def blog_posts(context, data):
        return {
            'blog_posts': data,
        }

Then usage

{% blog_posts data %}

and of course your blog_posts.html file that is used in the inclusion tag would do something like looping over the data

<div>
    {% for post in blog_posts %}
    <p>{{ post.name}}
    {% endfor %}
</div>

Upvotes: 1

rafalmp
rafalmp

Reputation: 4068

You can either render blog_posts.html to string and pass it as a variable to the other template:

from django.template.loader import get_template
blog_posts = get_template('/path/to/blog_posts.htm')
somevar = blog_posts.render({'foo': 'foo', 'bar': 'baz'})

then place {{ somevar }} in the other template - or just {% include '/path/to/blog_posts.html' %} in the other; the included template will have access to all variables passed to the 'parent' one.

Upvotes: 1

Related Questions