Is it possible to override an existing Django Template Tag? or is it necessary to customize the template file and create a new Template Tag?
Yes.
As django is basically a python library (as with everything in python) you can over-write anything you'd like.
It's not clear exactly what you'd like to do but it really is pretty easy to roll-your-own templatetag, the docs are pretty clear: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags
This is crazy basic but this is the kind of template I use to start building a custom template tag from:
myapp/templatetags/my_custom_tags.py
(must have __init__.py
in this directory)
from django import template
register = template.Library()
class CustomTag(template.Node):
def render(self, context):
context['my_custom_tag_context'] = "this is my custom tag, yeah"
return ''
@register.tag(name='get_custom_tag')
def get_custom_tag(parser, token):
return CustomTag()
Usage in your template goes like this:
{% load my_custom_tags %}
{% get_custom_tag %}
{{my_custom_tag_context}}
You probably want to parse the token
, and you probably want some kind of __init__
in the class, but it does go to show how basic it is.
You can browse through the existing 'default' templatetags, replicate and modify them to your heart's content.
There really is some great stuff there: https://github.com/django/django/blob/master/django/template/defaulttags.py
I was looking for the same answer, so figured I'd share my solution here. I wanted to override the default url template tag in django without having to use a custom template tag and load it in every template file.
The goal was to replace %20 (spaces) with + (pluses). Here's what I came up with...
In __init__.py
from django.template.defaulttags import URLNode
old_render = URLNode.render
def new_render(cls, context):
""" Override existing url method to use pluses instead of spaces
"""
return old_render(cls, context).replace("%20", "+")
URLNode.render = new_render
This page was useful https://github.com/django/django/blob/master/django/template/defaulttags.py
I assume by "an Existing Django Template Tag" you mean a tag in a different app.
Create a templatetags/tagfile.py
that registers a tag with the same name. Make sure that tagfile
is the same name that the template loads with {% load tagfile %}
for getting the original tag.
Also, make sure your app is listed after the original app in INSTALLED_APPS
.
register
object from the other library (the other library should have something like register = template.Library()
and then it registers tags by doing @register.tag
etc. You can import register
instead of instantiating your own, and do @register.tag(tag_name='existing_tag')
–
Intuit (templates.E003) 'admin_list' is used for multiple template tag modules: 'myapp.templatetags.admin_list', 'someapp.templatetags.admin_list'
. –
Few I am pretty sure you are asking for complete override of a django templatetag
.
The short answer is - Yes
, you can override an existing templatetag
.
Here is how to achieve it:
- You have to have your template directory included in the
settings
:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'your_app/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',
'django.template.context_processors.static',
],
},
},
]
- You have to include the app you want to override a
templatetag
for, in theINSTALLED_APPS
:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'your_app_name',
...
]
The important bit is to have your app after django's apps !
This is due to the way django works. We will get use right of that.
- Now, create a folder inside your app, named
templatetags
. It is important to have__init__.py
file inside thetemplatetags
, so django could understand it is a python package!:
your_app_name/templatetags/__init__.py
.
- Create the
templatetag
you want to override. In that example, i'll use theadmin_list.py
tag.
In that case, it should be placed like this:
your_app_name/templatetags/admin_list.py
- Now copy the entire content of the
admin_list.py
(VERY IMPORTANT!) fromdjango.contrib.admin.templatetags.admin_list.py
and modify whatever you want.
It is important to have the whole content of the django's admin admin_list.py
and not only a piece of code, else it would not work!
How it works:
Django is looking in your application for templatetags
folder and uses the template tags inside of it. It places yours template tags after the admin's
ones and in short - it overrides them since they are placed after django.admin
in the INSTALLED_APPS
.
Do not forget to:
./manage.py collectstatic
- set
DEBUG = False
in production.
I have tested it already for result_list(cl)
function override, and it is working.
This solution works event without custom html template files.
Hope that helps.
Yes.
As django is basically a python library (as with everything in python) you can over-write anything you'd like.
It's not clear exactly what you'd like to do but it really is pretty easy to roll-your-own templatetag, the docs are pretty clear: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags
This is crazy basic but this is the kind of template I use to start building a custom template tag from:
myapp/templatetags/my_custom_tags.py
(must have __init__.py
in this directory)
from django import template
register = template.Library()
class CustomTag(template.Node):
def render(self, context):
context['my_custom_tag_context'] = "this is my custom tag, yeah"
return ''
@register.tag(name='get_custom_tag')
def get_custom_tag(parser, token):
return CustomTag()
Usage in your template goes like this:
{% load my_custom_tags %}
{% get_custom_tag %}
{{my_custom_tag_context}}
You probably want to parse the token
, and you probably want some kind of __init__
in the class, but it does go to show how basic it is.
You can browse through the existing 'default' templatetags, replicate and modify them to your heart's content.
There really is some great stuff there: https://github.com/django/django/blob/master/django/template/defaulttags.py
If you don't want to depend on the order of your app inside the settings.py INSTALLED_APPS
, then you can try the following:
Create the templatetag function/class as usual. Say you want to override a templatetag named otherapp_tags.current_time
from an app named other_app
. First, create your own version of that function/class:
def my_current_time(format_string):
return datetime.datetime.now().strftime(format_string)
then, instead of registering this function/class inside YOUR apps namespace, patch the existing function from the other app:
from other_app.templatetags import otherapp_tags
otherapp_tags.register.tags['current_time'] = my_current_time
Typically you should do this inside your AppConfig
's ready()
method.
The actually most voted solution has one major drawback for me - you need to redefine all tags. For some projects, that can be a big drawback. How to solve that? As mentioned by m_floer, it's best to import the register instance from the outside module. So how it should look? Code was taken from Django Jazzmin:
What I want to do? Overwrite the only one template tag: get_side_menu
tag.
The tag is located in jazzmin.templatetags.jazzmin
, so in our app we will create module templatetags
with file jazzmin.py
. And the contents will be:
...
from jazzmin.templatetags.jazzmin import register
@register.simple_tag(takes_context=True, name="get_side_menu")
def get_side_menu(context: Context, using: str = "available_apps") -> List[Dict]:
... # your template tag code
This will override just and only selected Django template tag in the easiest way possible. Be aware, that it's for all apps in the given project!
You can override Django Template Tags. *You can see my answer explaining how to create Django Template Tags.
First, create templatetags
folder with __init__.py
(Empty file) and custom_tags.py
in core
folder where settings.py
is as shown below, then don't forget to restart server to apply custom_tags.py
to Django project. *Other names are fine for custom_tags.py
and you can see my answer explaining templatetags folder and load tag:
django-project
|-core
| |-settings.py
| └-templatetags # Here
| |-__init__.py
| └-custom_tags.py
|-templates
| └-index.html
|-app1
└-app2
And, don't forget to set core
to INSTALLED_APPS
in settings.py
to apply custom_tags.py
to Django project as shown below. *Setting core
to INSTALLED_APPS
also can collect the static files in core
folder to the root Django Project folder with python manage.py collectstatic
. I recommend to set core
to INSTALLED_APPS
before you start building your Django Project:
# "core/settings.py"
INSTALLED_APPS = [
# ...
'core', # Here
'app1',
'app2',
]
Next, override comment
tag in custom_tags.py
as shown below. *You can see the original comment tag in /django/template/defaulttags.py
:
# "custom_tags.py"
from django.template import Library, Node
register = Library()
@register.tag
def comment(parser, token):
parser.skip_past('endcomment')
return CommentNode()
class CommentNode(Node):
def render(self, context):
return 'This is not a comment.' # This part is changed.
Then, use the overridden comment tag as shown below:
# "templates/index.html"
{% load custom_tags %}
{% comment %}{% endcomment %}
Then, this below is displayed:
This is not a comment.
© 2022 - 2024 — McMap. All rights reserved.