2

In my django project, I have a base.html from which all my templates {% extends 'base.html' %}. In that base template I want to do this to a list of all my algorithms.

{% for algorithm in algorithms %}
   # list them out as links in nav bar
{% endfor %}

But I'm not passing algorithms to the base since it's just extending other templates.

I don't know how to solve this. My thought was to use {% load %} in the base template which would basically.

from algorithms.models import Algorithm
from django import template


register = template.Library()

def GetAlgorithmObjects():

  a = Algorithm.objects.all()

  return {'algorithms': a}

I'm not sure of how load works which would explain this failure. How would you actually implement this or should I go a different path.

Davey Browne
  • 25
  • 1
  • 4

2 Answers2

2

You would actually want to make a context processor to supply the algorithm objects to all templates. context_processors are just functions that return objects to be used as context within any view. So here is the code you need:

For this example, my app is called core. I have a python file in the app called context_processors and the function is myuser. Here is my function code:

from django.contrib.auth.models import User
from .models import MyUser

def myuser(request):
    try:
        user = User.objects.get(pk=request.user.pk)
    except User.DoesNotExist:
        user = None

    if user:
        myuser = MyUser.objects.get(user=user)
        return {'myuser': myuser}
    else:
        # load a default user for testing
        myuser = MyUser.objects.all()[0]
        return {'myuser': myuser}

The myuser() function just returns my extended User model. I created this so I could have the MyUser object available in all templates.

Then add this context_processor to you settings.py:

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    # other default context processors
    'core.context_processors.myuser',
    )
Aaron Lelevier
  • 19,850
  • 11
  • 76
  • 111
1

You can make it with inclusion tag https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags

In your app algorithms create directory templatetags and put a file in it named algorithms_tags.py (of course in this directory there must be a file named __init__.py)

Then the content of the file is similar to what you wrote:

from algorithms.models import Algorithm
from django import template

register = template.Library()

@register.inclusion_tag('algorithms/show_algorithms.html')
def show_algorithms():
    a = Algorithm.objects.all()
    return {'algorithms': a}

Then you need a template located at algorithms/templates/algorithms/show_algorithms.html with the following content:

{% for algorithm in algorithms %}
   # list them out as links in nav bar
{% endfor %}

You can use it in your base.html as follows:

{% load algorithms_tags %}

{% show_algorithms %}

Some explanations:

  • In {% load algorithms_tags %} "algorithms_tags" is the name of the .py file created in the templatetags directory (without the extension)
  • In {% show_algorithms %} "show_algorithms" is the name of the function decorated with register.inclusion_tag in inclusion_tag.py
VStoykov
  • 1,705
  • 12
  • 15
  • How would I make it so that show_algorithm takes a string as an argument? Something like {% show_algorithms("statistics") %} – Davey Browne Aug 13 '14 at 21:39
  • It's simple. just add the argument to the function `def show_algorithms(some_name):` and in your template you use `{% show_algorithms "statistics" %}` or `{% show_algorithms some_name="statistics" %}` where `some_name` is the name of function argument. – VStoykov Aug 13 '14 at 21:53