0

I'm just learning Django and Python and want to be sure I'm doing things the right DRY way and I'm sure there's a MUCH easier way to do this...

Right now, I have the following base_template_tags.py as it's own app (added into settings.py and loaded on the HTML template {% load ... %} that allows me to access the year as an HTML tag via {% cd_year %} and/or the email address as { cd_email }. It works... but it's a hack.

Is there a better way?

from datetime import datetime
from django import template

register = template.Library()

@register.simple_tag
def current_time(format_string):
    return datetime.datetime.now().strftime(format_string)

@register.simple_tag
def cd_year():
    return datetime.now().year

@register.simple_tag
def cd_email():
    return 'pp@pp.com'
ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
Infamouse
  • 21
  • 6
  • What about [`now`](https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#now)? – mshsayem Dec 07 '19 at 16:23
  • oh, sorry.. i should have clarified... i have a bunch of constants that I'd like to access across the application... not just this one for the date. – Infamouse Dec 07 '19 at 16:28
  • The correct answer to this question is [context processors](https://docs.djangoproject.com/en/2.2/ref/templates/api/#using-requestcontext), not template tags. – Daniel Roseman Dec 08 '19 at 09:27

2 Answers2

0

As you guessed, there is a much more easier way built-in to django:

{% now "Y" %}

Edit

As you mentioned in the comments that you want to share a bunch of template tags among all of your apps, you can override libraries dictionary and add your custom template tags there.

Read more about that in the docs

and for your templates:

{% load your_template_tags_file_name %}


{% cd_year %}

Edit 2

This is how the TEMPLATES part of your settings.py should look like:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
            'libraries': {      # <-----------
                'global_tags': 'template_tags.global_tags',
                'admin.urls': 'django.contrib.admin.templatetags.admin_urls',
            },
        },
    },
]

and your directory structure should be like:

<your_project_dir>
├── __init__.py
├── settings.py
├── template_tags
│   ├── global_tags.py
│   ├── __init__.py
...

the global_tags.py file should contain your template tag definition and registration, as:

from datetime import datetime
from django import template

register = template.Library()

@register.simple_tag
def current_time(format_string):
    return datetime.now().strftime(format_string)

@register.simple_tag
def cd_year():
    return datetime.now().year

@register.simple_tag
def cd_email():
    return 'pp@pp.com'

and for each template that's going to use those custom template tags:

{% load global_tags %}


{% cd_year %}
Community
  • 1
  • 1
Pedram Parsian
  • 3,750
  • 3
  • 19
  • 34
  • oh, sorry.. I would like to do this for a bunch of constants.. like {{ application_name }} , {{ contact_email }}, and the like. – Infamouse Dec 07 '19 at 16:30
  • So you want to define your all of your custom `template_tags` once and re-use them in all the apps? – Pedram Parsian Dec 07 '19 at 16:32
  • @P'P' Check out [this](https://stackoverflow.com/a/41492671/9733868) answer; that's my preferred way of doing it. – Pedram Parsian Dec 07 '19 at 16:36
  • Also from the [docs](https://docs.djangoproject.com/en/2.2/topics/templates/#module-django.template.backends.django). – Pedram Parsian Dec 07 '19 at 16:37
  • got it, that's pretty much what I'm doing now (added as a library in TEMPLATES in static.py as well as INSTALLED_APPS). It works, but I was just curious if there was a such thing as a global context object or the like. i.e. I moved these definitions to this template_tags bit to not have to add the values in the various views. i had this before which had to be constantly repeated - – Infamouse Dec 07 '19 at 16:43
  • def contact(request): assert isinstance(request, HttpRequest) return render( request, 'misc/contact.html', { 'year':constants.cd_year, 'email':constants.cd_email } ) – Infamouse Dec 07 '19 at 16:45
  • i.e. I want to access these constants via {{ STATIC_VARIABLE_NAME }} rather than by calling the function {% FUNCTION_THAT_RETURNS_STATIC_VALUE %} – Infamouse Dec 07 '19 at 16:46
  • Well, if you shared those template tags among all the apps (with either your approach or using `libraries`), you have access to them **directly** in the templates (after loading it); as in `{% cd_year %}`; So you don't need a function `def contact...` to access them. – Pedram Parsian Dec 07 '19 at 16:51
  • just tried.. just tried that, but got the following: – Infamouse Dec 07 '19 at 16:58
  • Invalid block tag on line 43: 'cd_name'. Did you forget to register or load this tag? – Infamouse Dec 07 '19 at 16:58
  • Did you load your template_tag at the top of your html template? – Pedram Parsian Dec 07 '19 at 17:18
  • @register.simple_tag – Infamouse Dec 07 '19 at 17:26
  • Yes, you need to register them; But you should also ***load*** them in your html templates as well (`{% load base_template_tags %}`) – Pedram Parsian Dec 07 '19 at 17:41
  • @P'P' if you can't get it working properly, please let me know to include a full example. – Pedram Parsian Dec 07 '19 at 18:00
  • thanks, please do if you could. I have it working like this, but it's still a function and not just a variable declaration.@register.simple_tag def cd_email(): return 'pp@pp.com' – Infamouse Dec 07 '19 at 19:05
  • Is this something that belong in a Context Processor? and if so, how can I configure that? – Infamouse Dec 07 '19 at 19:06
  • right, but this handles everything as a function. cd_year() is a function call and not a reference to the static variable. That's what I was asking about a better way. Also, {{ cd_year }} doesn't seem to come back with anything for me. {% cd_year %} does however. – Infamouse Dec 07 '19 at 20:01
  • So what do you mean by a _better_ way? As I mentioned earlier, it's better to use django's default template-tags when it's possible (e.g. current year); but for other variables (either _static_ or _dynamic_) you should use template tags, or context processor (check out [this](https://stackoverflow.com/a/433209/9733868)). and I make a mistake about `{{ cd_year}}`, it should be `{% cd_year %}`. thanks for mentioning it. – Pedram Parsian Dec 07 '19 at 20:11
  • AWESOME! Yes, exactly that. Perfect! Thanks so much for your help. – Infamouse Dec 07 '19 at 23:04
0

You can used below code in .html

{% block content %}
{% load staticfiles %}
{% endblock %}
  1. Create a new folder “static” in the root of the main project. Same level as the “templates” directory.

  2. Add this code to your base template file (__base.html).

    {% load staticfiles %}

  3. Use this to load the files.

  4. Add this to your settings.py file.

    STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ]

Create global context: You have create App inside context_processor.py file In context_processor file written:

from app.model import *
from django.contrib.auth.models import user
def employee_processor(request):
    try:
        emp_obj= Employees.object.filter(user=request.user)
        return { ’employee’:emp_obj}
    except:
        user_obj=User.object.filter(id=request.user)
        return { ’employee’: user_obj}

Add your context processor in your setting py file:

TEMPLATES = [{
    # whatever comes before
    'OPTIONS': {
        'context_processors': [
             # whatever comes before
                   "your_app.context_processors.employee_processor",
        ],
    }
}]

Then you can used global variables in your HTML template

{{ employee }}
{{ employee.name }}
  • Thanks. How can I get to the constants stored within those static files? I'm really looking for the right place to define global constants.. such as `email` or the like – Infamouse Dec 07 '19 at 19:08