0

I have a large Django Project that has hundreds of views already. I am creating a tasks feature where users are able to complete specific tasks associated with the specific application in the project they are using. I have multiple interfaces (aka Django apps in the project) : admin, management, onsite, etc... and each interface has its own navigation with a tasks link.

What I want is to be able to change the color of this link if a user is in an interface where a task has yet to be completed.

This is easy to check in each view and then I could universally render the correct color for the link based on a variable passed into the view, but that is extremely tedious with hundreds of views.

I suppose I could add a filter in each interface/Django App to simplify this a bit, but is that the most simple solution?

Here is an example of the method I want to be called in each interface's navigation:

from objects_client.task_models.task_models import Tasks


def does_interface_have_open_tasks(current_interface, db_alias):
    if Tasks.objects.using(db_alias)\
            .filter(interface=current_interface, completed=0).exists():
        return True
    return False

ViaTech
  • 2,143
  • 1
  • 16
  • 51
  • 1
    This is a job for a context processor or custom template tag. – Daniel Roseman Apr 23 '19 at 22:23
  • I am looking into this today @DanielRoseman, I think the `ContextProcessor` is the way to go for the templates in each application doing a bit of research, thanks! – ViaTech Apr 24 '19 at 15:45

1 Answers1

0

I ended up using a Context Processor to solve my needs like I show below:

import traceback
from objects_client.task_models.task_models import Tasks


def universally_used_data(request):
    # I use multiple DBs
    db_alias = request.session.get('db_alias')

    # dictionary for global context values
    dictionary_to_return = dict()

    # interfaces and URL equivalents
    interface_dictionary = {
        'adm': 'admin',
        'mgt': 'management',
        'onsite': 'onsite',
        'secu': 'security',
        'maint': 'maintenance'
    }

    try:
        # get interface url
        short_url = request.path[1:-1].split('/')[1]
        # get interface from dictionary above
        interface = interface_dictionary.get(short_url)

        dictionary_to_return['SHORT_URL'] = short_url

        dictionary_to_return['INTERFACE'] = interface

        # see if there is an open task...
        if Tasks.objects.using(db_alias) \
                .filter(interface=interface, completed=0).exists():

            dictionary_to_return['OPEN_TASKS'] = True
        else:
            dictionary_to_return['OPEN_TASKS'] = False

    except Exception as ex:
        print(ex, traceback.format_exc())

    return dictionary_to_return


Here is how I load the Context Processor:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',

        'DIRS': [
            os.path.join(BASE_DIR, 'templates'),
            ... 
        ]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
               ... 
                # custom processors
                'utils.context_processors.context_processors.universally_used_data'
            ],
        },
    },
]

Then I can just call the this variable in the template like so to change an HTML element's color, no {% load [whatever] %} or anything:

{% if OPEN_TASKS %}
    style="color:red;"
{% endif %}

Thank you @Daniel Roseman for the suggestion/comment. This had me stumped for a bit :)

ViaTech
  • 2,143
  • 1
  • 16
  • 51