How to do it...

An advanced custom template tag consists of a function that parses the arguments that are passed to the tag, and the Node class that renders the output of the tag or modifies the template context. Perform the following steps to create the {% load_objects %} template tag:

  1. First, let's create the function that handles parsing the template tag arguments, as follows:
# utils/templatetags/utility_tags.py
from django import template
from django.apps import apps

register = template.Library()


"""TAGS"""


@register.tag
def load_objects(parser, token):
"""
Gets a queryset of objects of the model specified by app and
model names

Usage:
{% load_objects [<manager>.]<method>
from <app_name>.<model_name>
[limit <amount>]
as <var_name> %}

Examples:
{% load_objects latest_published from people.Person
limit 3 as people %}
{% load_objects site_objects.all from news.Article
as articles %}
{% load_objects site_objects.all from news.Article
limit 3 as articles %}
"""
limit_count = None
try:
(tag_name, manager_method,
str_from, app_model,
str_limit, limit_count,
str_as, var_name) = token.split_contents()
except ValueError:
try:
(tag_name, manager_method,
str_from, app_model,
str_as, var_name) = token.split_contents()
except ValueError:
tag_name = token.contents.split()[0]
raise template.TemplateSyntaxError(
f"{tag_mame} tag requires the following syntax: "
f"{{% {tag_mame} [<manager>.]<method> from "
"<app_name>.<model_name> [limit <amount>] "
"as <var_name> %}")
try:
app_name, model_name = app_model.split(".")
except ValueError:
raise template.TemplateSyntaxError(
"load_objects tag requires application name "
"and model name, separated by a dot")
model = apps.get_model(app_name, model_name)
return ObjectsNode(model, manager_method, limit_count,
var_name)
  1. Then, we will create the custom ObjectsNode class in the same file, extending from the base template.Node, as shown in the following code:
class ObjectsNode(template.Node):
def __init__(self, model, manager_method, limit, var_name):
self.model = model
self.manager_method = manager_method
self.limit = template.Variable(limit) if limit else None
self.var_name = var_name

def render(self, context):
if "." in self.manager_method:
manager, method = self.manager_method.split(".")
else:
manager = "_default_manager"
method = self.manager_method

model_manager = getattr(self.model, manager)
fallback_method = self.model._default_manager.none
qs = getattr(model_manager, method, fallback_method)()
limit = None
if self.limit:
try:
limit = self.limit.resolve(context)
except template.VariableDoesNotExist:
limit = None
context[self.var_name] = qs[:limit] if limit else qs
return ""
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.198.49