Defining Metrics
Learn how to define metrics in Djing.
Djing metrics allow you to quickly gain insight on key business indicators for your application. For example, you may define a metric to display the total number of users added to your application per day, or the amount of weekly sales for a given product.
Djing offers several types of built-in metrics: value, table, partition, and progress. We’ll examine each type of metric and demonstrate their usage below.
Value Metrics
Value metrics display a single value and, if desired, its change compared to a previous time interval. For example, a value metric might display the total number of users created in the last thirty days compared with the previous thirty days:

Value metrics may be generated using the djing:value
Artisan command. By default, all new metrics will be placed in the djing_admin/app/Djing/Metrics
directory:
commander djing:value NewUsers
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Value import Value
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class ValueMetric(Value):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.count(request, Post)
def ranges(self):
return {
30: "30 Days",
60: "60 Days",
365: "365 Days",
"TODAY": "Today",
"MTD": "Month To Date",
"QTD": "Quarter To Date",
"YTD": "Year To Date",
}
Value Query Types
Value metrics don’t only ship with a count
helper. You may also use a variety of other aggregate functions when building your metric. Let’s explore each of them now.
— Average
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Value import Value
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class ValueMetric(Value):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.average(request, Post)
# ...
— Sum
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Value import Value
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class ValueMetric(Value):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.sum(request, Post)
# ...
— Max
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Value import Value
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class ValueMetric(Value):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.max(request, Post)
# ...
— Min
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Value import Value
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class ValueMetric(Value):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.min(request, Post)
# ...
Value Ranges
Every value metric class contains a ranges
method. This method determines the ranges that will be available in the value metric’s range selection menu. The dict’s keys determine the number of days that should be included in the query, while the values determine the “human readable” text that will be placed in the range selection menu. Of course, you are not required to define any ranges at all:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Value import Value
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class ValueMetric(Value):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.count(request, Post)
def ranges(self):
return {
30: "30 Days",
60: "60 Days",
365: "365 Days",
"TODAY": "Today",
"YESTERDAY": "Yesterday",
"THIS_WEEK": "This Week",
"MTD": "Month To Date",
"QTD": "Quarter To Date",
"YTD": "Year To Date",
}
Zero Result Values
By default, Djing will handle results of 0
as a result containing no data. This may not always be correct, which is why you can use the allow_zero_result
method to indicate that 0
is a valid value result:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Value import Value
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class ValueMetric(Value):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.count(request, Post).allow_zero_results()
# ...
Formatting the Value
You can add a prefix and / or suffix to the Value metric’s result by invoking the prefix
and suffix
methods when returning the ValueResult
instance:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Value import Value
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class ValueMetric(Value):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.count(request, Post)
.prefix("$")
.suffix("per unit")
# ...
You may also use the currency
method to specify that a given value result represents a currency value:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Value import Value
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class ValueMetric(Value):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.count(request, Post).currency()
# ...
By default, the currency symbol will be $
, but you may also specify your own currency symbol by passing the symbol as an argument to the currency
method:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Value import Value
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class ValueMetric(Value):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.count(request, Post).currency("£")
# ...
Progress Metric
Progress metrics display current progress against a target value within a bar chart. For example, a progress metric might display the number of users registered for the given month compared to a target goal:

Progress metrics may be generated using the djing:progress
Artisan command. By default, all new metrics will be placed in the djing_admin/app/Djing/Metrics
directory:
commander djing:progress NewPosts
Once your progress metric class has been generated, you’re ready to customize it. Each progress metric class contains a calculate
method. This method should return a Djing.Metrics.ProgressResult
object. Don’t worry, Djing ships with a variety of helpers for quickly generating results.
In this example, we are using the count
helper to determine if we have reached our new post creation goal for the month. The count
helper will automatically perform a count
query against the specified Django model:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Progress import Progress
from djing.core.Http.Requests.DjingRequest import DjingRequest
from posts.models import Post
class NewPosts(Progress):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
def progress_callback(query: QuerySet) -> QuerySet:
return query
return self.count(request, Post, progress_callback, target=100)
def ranges(self):
return {
30: "30 Days",
60: "60 Days",
365: "365 Days",
"TODAY": "Today",
"MTD": "Month To Date",
"QTD": "Quarter To Date",
"YTD": "Year To Date",
}
Sum
Progress metrics don’t only ship with a count
helper. You may also use the sum
aggregate method when building your metric. For example, the following call to the sum
method will display a progress metric with the sum of the completed transaction amounts against a target sales goal:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Progress import Progress
from djing.core.Http.Requests.DjingRequest import DjingRequest
from transactions.models import Transaction
class NewPosts(Progress):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
def progress_callback(query: QuerySet) -> QuerySet:
return query.where(completed=True)
return self.sum(
request, Transaction, progress_callback, column='amount', target=2000
)
# ...
Formatting the Progress value
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Progress import Progress
from djing.core.Http.Requests.DjingRequest import DjingRequest
from transactions.models import Transaction
class NewPosts(Progress):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
def progress_callback(query: QuerySet) -> QuerySet:
return query.where(completed=True)
return self
.sum(
request,
Transaction,
progress_callback,
column='amount',
target=2000,
)
.prefix("$")
# ...
Partition Metrics
Partition metrics displays a pie chart of values. For example, a partition metric might display the total number of users for each billing plan offered by your application:

Partition metrics may be generated using the djing:partition
Artisan command. By default, all new metrics will be placed in the djing_admin/app/Djing/Metrics
directory:
commander djing:partition UsersPerPlan
Once your partition metric class has been generated, you’re ready to customize it. Each partition metric class contains a calculate
method. This method should return a Djing.Metrics.PartitionResult
object. Don’t worry, Djing ships with a variety of helpers for quickly generating results.
In this example, we are using the count
helper, which will automatically perform a count
query against the specified Eloquent model and retrieve the number of models belonging to each distinct value of your specified “group by” column:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Partition import Partition
from djing.core.Http.Requests.DjingRequest import DjingRequest
from products.models import Product
class UsersPerPlan(Partition):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.count(request, Product, group_by_column="price")
def uri_key(self):
return "users-per-plan"
Partition Query Types
Partition metrics don’t only ship with a count
helper. You may also use a variety of other aggregate functions when building your metric.
— Average
The average
method may be used to calculate the average of a given column within distinct groups. For example, the following call to the average
method will display a pie chart with the average order price for each department of the company:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Partition import Partition
from djing.core.Http.Requests.DjingRequest import DjingRequest
from products.models import Product
class UsersPerPlan(Partition):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.average(request, Product, group_by_column="price")
# ...
— Sum
The sum
method may be used to calculate the sum of a given column within distinct groups. For example, the following call to the sum
method will display a pie chart with the sum of all order prices for each department of the company:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Partition import Partition
from djing.core.Http.Requests.DjingRequest import DjingRequest
from products.models import Product
class UsersPerPlan(Partition):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.sum(request, Product, group_by_column="price")
# ...
— Max
The max
method may be used to calculate the max of a given column within distinct groups. For example, the following call to the max
method will display a pie chart with the maximum order price for each department of the company:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Partition import Partition
from djing.core.Http.Requests.DjingRequest import DjingRequest
from products.models import Product
class UsersPerPlan(Partition):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.average(request, Product, group_by_column="price")
# ...
— Min
The min
method may be used to calculate the min of a given column within distinct groups. For example, the following call to the min
method will display a pie chart with the minimum order price for each department of the company:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.Partition import Partition
from djing.core.Http.Requests.DjingRequest import DjingRequest
from products.models import Product
class UsersPerPlan(Partition):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return self.average(request, Product, group_by_column="price")
# ...
Table Metrics
Table metrics allow you to display custom lists of links along with a list of actions, as well as an optional icon.
Table metrics may be generated using the djing:table
Artisan command. By default, all new metrics will be placed in the djing_admin/app/Djing/Metrics
directory:
commander djing:table NewReleases
Once your table metric class has been generated, you’re ready to customize it. Each table metric class contains a calculate
method. This method should return an array of Djing.Metrics.MetricTableRow
objects. Each metric row allows you to specify a title and subtitle, which will be displayed stacked on the row:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.MetricTableRow import MetricTableRow
from djing.core.Metrics.Table import Table
from djing.core.Http.Requests.DjingRequest import DjingRequest
class NewReleases(Table):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return [
MetricTableRow.make()
.title("v1.0")
.subtitle("Initial release of Djing Admin"),
MetricTableRow.make()
.title("v2.0")
.subtitle("The second major series of Djing Admin"),
]
Adding Actions to Table Rows
While table metrics are great for showing progress, documentation links, or recent entries to your models, they become even more powerful by attaching actions to them.

You can use the actions
method to return an array of Djing.Menu.MenuItem
instances, which will be displayed in a dropdown menu:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.MetricTableRow import MetricTableRow
from djing.core.Metrics.Table import Table
from djing.core.Http.Requests.DjingRequest import DjingRequest
class NewReleases(Table):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return [
MetricTableRow.make()
.title("v1.0")
.subtitle("Initial release of Djing Admin")
.action(lambda: [
MenuItem::externalLink('View release notes', '/releases/1.0'),
]),
MetricTableRow.make()
.title("v2.0")
.subtitle("The second major series of Djing Admin")
.action(lambda: [
MenuItem::externalLink('View release notes', '/releases/2.0'),
]),
]
Displaying Icons on Table Rows
Table metrics also support displaying an icon to the left of the title and subtitle for each row. You can use this information to visually delineate different table rows by type, or by using them to show progress on an internal process.

To show an icon on your table metric row, use the icon
method and pass in the key for the icon you wish to use:
from typing import Optional
from django.db.models import Model
from djing.core.Metrics.MetricTableRow import MetricTableRow
from djing.core.Metrics.Table import Table
from djing.core.Http.Requests.DjingRequest import DjingRequest
class NewReleases(Table):
def calculate(self, request: DjingRequest, model: Optional[Model] = None):
return [
MetricTableRow.make()
.icon("check-circle")
.icon_class("text-green-500")
.title("v1.0")
.subtitle("Initial release of Djing Admin")
.action(lambda: [
MenuItem::externalLink('View release notes', '/releases/1.0'),
]),
MetricTableRow.make()
.icon("check-circle")
.icon_class("text-green-500")
.title("v2.0")
.subtitle("The second major series of Djing Admin")
.action(lambda: [
MenuItem::externalLink('View release notes', '/releases/2.0'),
]),
]
Last updated