text: from django.core.exceptions import ValidationError
  from django.db import models
  from django.urls import reverse
  from mptt.models import MPTTModel, TreeForeignKey
  
  from extras.utils import extras_features
  from netbox.models import NestedGroupModel, PrimaryModel
  from utilities.querysets import RestrictedQuerySet
  
  
  __all__ = (
      'Tenant',
      'TenantGroup',
  )
  
  
  @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
  class TenantGroup(NestedGroupModel):
      """
      An arbitrary collection of Tenants.
      """
      name = models.CharField(
          max_length=100,
          verbose_name="名称",
          unique=True
      )
      slug = models.SlugField(
          verbose_name="唯一标识",
          max_length=100,
          unique=True
      )
      parent = TreeForeignKey(
          to='self',
          on_delete=models.CASCADE,
          related_name='children',
          blank=True,
          null=True,
          db_index=True
      )
      description = models.CharField(
          verbose_name="描述",
          max_length=200,
          blank=True
      )
  
      class Meta:
          ordering = ['name']
  
      def get_absolute_url(self):
          return reverse('tenancy:tenantgroup', args=[self.pk])
  
  
  @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
  class Tenant(PrimaryModel):
      """
      A Tenant represents an organization served by the NetBox owner. This is typically a customer or an internal
      department.
      """
      name = models.CharField(
          max_length=100,
          verbose_name="租户名",
          unique=True
      )
      slug = models.SlugField(
          max_length=100,
          unique=True
      )
      group = models.ForeignKey(
          to='tenancy.TenantGroup',
          on_delete=models.SET_NULL,
          verbose_name="租户组",
          related_name='tenants',
          blank=True,
          null=True
      )
      description = models.CharField(
          max_length=200,
          verbose_name="描述",
          blank=True
      )
      comments = models.TextField(
          verbose_name="评论",
          blank=True
      )
  
      objects = RestrictedQuerySet.as_manager()
  
      clone_fields = [
          'group', 'description',
      ]
  
      class Meta:
          ordering = ['name']
  
      def __str__(self):
          return self.name
  
      def get_absolute_url(self):
          return reverse('tenancy:tenant', args=[self.pk])
  