From a61201217826ae7e94a96e9bf07e5ef21d672059 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Mon, 23 Jan 2017 18:23:55 +0100 Subject: [PATCH] add @python_2_unicode_compatible decorator to models for python2 compatibility --- netbox/circuits/models.py | 5 +++++ netbox/dcim/models.py | 23 +++++++++++++++++++++++ netbox/extras/models.py | 8 ++++++++ netbox/ipam/models.py | 10 ++++++++++ netbox/secrets/models.py | 5 ++++- netbox/tenancy/models.py | 3 +++ 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/netbox/circuits/models.py b/netbox/circuits/models.py index 9972e564f..6a0380dd5 100644 --- a/netbox/circuits/models.py +++ b/netbox/circuits/models.py @@ -1,6 +1,7 @@ from django.contrib.contenttypes.fields import GenericRelation from django.core.urlresolvers import reverse from django.db import models +from django.utils.encoding import python_2_unicode_compatible from dcim.fields import ASNField from extras.models import CustomFieldModel, CustomFieldValue @@ -33,6 +34,7 @@ def humanize_speed(speed): return '{} Kbps'.format(speed) +@python_2_unicode_compatible class Provider(CreatedUpdatedModel, CustomFieldModel): """ Each Circuit belongs to a Provider. This is usually a telecommunications company or similar organization. This model @@ -67,6 +69,7 @@ class Provider(CreatedUpdatedModel, CustomFieldModel): ]) +@python_2_unicode_compatible class CircuitType(models.Model): """ Circuits can be organized by their functional role. For example, a user might wish to define CircuitTypes named @@ -85,6 +88,7 @@ class CircuitType(models.Model): return "{}?type={}".format(reverse('circuits:circuit_list'), self.slug) +@python_2_unicode_compatible class Circuit(CreatedUpdatedModel, CustomFieldModel): """ A communications circuit connects two points. Each Circuit belongs to a Provider; Providers may have multiple @@ -141,6 +145,7 @@ class Circuit(CreatedUpdatedModel, CustomFieldModel): commit_rate_human.admin_order_field = 'commit_rate' +@python_2_unicode_compatible class CircuitTermination(models.Model): circuit = models.ForeignKey('Circuit', related_name='terminations', on_delete=models.CASCADE) term_side = models.CharField(max_length=1, choices=TERM_SIDE_CHOICES, verbose_name='Termination') diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index dde959e23..d29ca745d 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -8,6 +8,7 @@ from django.core.urlresolvers import reverse from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.db.models import Count, Q, ObjectDoesNotExist +from django.utils.encoding import python_2_unicode_compatible from circuits.models import Circuit from extras.models import CustomFieldModel, CustomField, CustomFieldValue @@ -199,6 +200,7 @@ class SiteManager(NaturalOrderByManager): return self.natural_order_by('name') +@python_2_unicode_compatible class Site(CreatedUpdatedModel, CustomFieldModel): """ A Site represents a geographic location within a network; typically a building or campus. The optional facility @@ -265,6 +267,7 @@ class Site(CreatedUpdatedModel, CustomFieldModel): # Racks # +@python_2_unicode_compatible class RackGroup(models.Model): """ Racks can be grouped as subsets within a Site. The scope of a group will depend on how Sites are defined. For @@ -289,6 +292,7 @@ class RackGroup(models.Model): return "{}?group_id={}".format(reverse('dcim:rack_list'), self.pk) +@python_2_unicode_compatible class RackRole(models.Model): """ Racks can be organized by functional role, similar to Devices. @@ -313,6 +317,7 @@ class RackManager(NaturalOrderByManager): return self.natural_order_by('site__name', 'name') +@python_2_unicode_compatible class Rack(CreatedUpdatedModel, CustomFieldModel): """ Devices are housed within Racks. Each rack has a defined height measured in rack units, and a front and rear face. @@ -477,6 +482,7 @@ class Rack(CreatedUpdatedModel, CustomFieldModel): # Device Types # +@python_2_unicode_compatible class Manufacturer(models.Model): """ A Manufacturer represents a company which produces hardware devices; for example, Juniper or Dell. @@ -494,6 +500,7 @@ class Manufacturer(models.Model): return "{}?manufacturer={}".format(reverse('dcim:devicetype_list'), self.slug) +@python_2_unicode_compatible class DeviceType(models.Model, CustomFieldModel): """ A DeviceType represents a particular make (Manufacturer) and model of device. It specifies rack height and depth, as @@ -608,6 +615,7 @@ class DeviceType(models.Model, CustomFieldModel): return bool(self.subdevice_role is False) +@python_2_unicode_compatible class ConsolePortTemplate(models.Model): """ A template for a ConsolePort to be created for a new Device. @@ -623,6 +631,7 @@ class ConsolePortTemplate(models.Model): return self.name +@python_2_unicode_compatible class ConsoleServerPortTemplate(models.Model): """ A template for a ConsoleServerPort to be created for a new Device. @@ -638,6 +647,7 @@ class ConsoleServerPortTemplate(models.Model): return self.name +@python_2_unicode_compatible class PowerPortTemplate(models.Model): """ A template for a PowerPort to be created for a new Device. @@ -653,6 +663,7 @@ class PowerPortTemplate(models.Model): return self.name +@python_2_unicode_compatible class PowerOutletTemplate(models.Model): """ A template for a PowerOutlet to be created for a new Device. @@ -706,6 +717,7 @@ class InterfaceManager(models.Manager): }).order_by(*ordering) +@python_2_unicode_compatible class InterfaceTemplate(models.Model): """ A template for a physical data interface on a new Device. @@ -725,6 +737,7 @@ class InterfaceTemplate(models.Model): return self.name +@python_2_unicode_compatible class DeviceBayTemplate(models.Model): """ A template for a DeviceBay to be created for a new parent Device. @@ -744,6 +757,7 @@ class DeviceBayTemplate(models.Model): # Devices # +@python_2_unicode_compatible class DeviceRole(models.Model): """ Devices are organized by functional role; for example, "Core Switch" or "File Server". Each DeviceRole is assigned a @@ -763,6 +777,7 @@ class DeviceRole(models.Model): return "{}?role={}".format(reverse('dcim:device_list'), self.slug) +@python_2_unicode_compatible class Platform(models.Model): """ Platform refers to the software or firmware running on a Device; for example, "Cisco IOS-XR" or "Juniper Junos". @@ -789,6 +804,7 @@ class DeviceManager(NaturalOrderByManager): return self.natural_order_by('name') +@python_2_unicode_compatible class Device(CreatedUpdatedModel, CustomFieldModel): """ A Device represents a piece of physical hardware mounted within a Rack. Each Device is assigned a DeviceType, @@ -968,6 +984,7 @@ class Device(CreatedUpdatedModel, CustomFieldModel): return RPC_CLIENTS.get(self.platform.rpc_client) +@python_2_unicode_compatible class ConsolePort(models.Model): """ A physical console port within a Device. ConsolePorts connect to ConsoleServerPorts. @@ -1011,6 +1028,7 @@ class ConsoleServerPortManager(models.Manager): }).order_by('device', 'name_as_integer') +@python_2_unicode_compatible class ConsoleServerPort(models.Model): """ A physical port within a Device (typically a designated console server) which provides access to ConsolePorts. @@ -1027,6 +1045,7 @@ class ConsoleServerPort(models.Model): return self.name +@python_2_unicode_compatible class PowerPort(models.Model): """ A physical power supply (intake) port within a Device. PowerPorts connect to PowerOutlets. @@ -1064,6 +1083,7 @@ class PowerOutletManager(models.Manager): }).order_by('device', 'name_padded') +@python_2_unicode_compatible class PowerOutlet(models.Model): """ A physical power outlet (output) within a Device which provides power to a PowerPort. @@ -1080,6 +1100,7 @@ class PowerOutlet(models.Model): return self.name +@python_2_unicode_compatible class Interface(models.Model): """ A physical data interface within a Device. An Interface can connect to exactly one other Interface via the creation @@ -1176,6 +1197,7 @@ class InterfaceConnection(models.Model): ]) +@python_2_unicode_compatible class DeviceBay(models.Model): """ An empty space within a Device which can house a child device @@ -1205,6 +1227,7 @@ class DeviceBay(models.Model): raise ValidationError("Cannot install a device into itself.") +@python_2_unicode_compatible class Module(models.Model): """ A Module represents a piece of hardware within a Device, such as a line card or power supply. Modules are used only diff --git a/netbox/extras/models.py b/netbox/extras/models.py index 31f959dd0..f06d0aa29 100644 --- a/netbox/extras/models.py +++ b/netbox/extras/models.py @@ -8,6 +8,7 @@ from django.core.validators import ValidationError from django.db import models from django.http import HttpResponse from django.template import Template, Context +from django.utils.encoding import python_2_unicode_compatible from django.utils.safestring import mark_safe @@ -93,6 +94,7 @@ class CustomFieldModel(object): return OrderedDict([(field, None) for field in fields]) +@python_2_unicode_compatible class CustomField(models.Model): obj_type = models.ManyToManyField(ContentType, related_name='custom_fields', verbose_name='Object(s)', limit_choices_to={'model__in': CUSTOMFIELD_MODELS}, @@ -153,6 +155,7 @@ class CustomField(models.Model): return serialized_value +@python_2_unicode_compatible class CustomFieldValue(models.Model): field = models.ForeignKey('CustomField', related_name='values') obj_type = models.ForeignKey(ContentType, related_name='+', on_delete=models.PROTECT) @@ -183,6 +186,7 @@ class CustomFieldValue(models.Model): super(CustomFieldValue, self).save(*args, **kwargs) +@python_2_unicode_compatible class CustomFieldChoice(models.Model): field = models.ForeignKey('CustomField', related_name='choices', limit_choices_to={'type': CF_TYPE_SELECT}, on_delete=models.CASCADE) @@ -207,6 +211,7 @@ class CustomFieldChoice(models.Model): CustomFieldValue.objects.filter(field__type=CF_TYPE_SELECT, serialized_value=str(pk)).delete() +@python_2_unicode_compatible class Graph(models.Model): type = models.PositiveSmallIntegerField(choices=GRAPH_TYPE_CHOICES) weight = models.PositiveSmallIntegerField(default=1000) @@ -231,6 +236,7 @@ class Graph(models.Model): return template.render(Context({'obj': obj})) +@python_2_unicode_compatible class ExportTemplate(models.Model): content_type = models.ForeignKey(ContentType, limit_choices_to={'model__in': EXPORTTEMPLATE_MODELS}) name = models.CharField(max_length=100) @@ -264,6 +270,7 @@ class ExportTemplate(models.Model): return response +@python_2_unicode_compatible class TopologyMap(models.Model): name = models.CharField(max_length=50, unique=True) slug = models.SlugField(unique=True) @@ -328,6 +335,7 @@ class UserActionManager(models.Manager): self.log_bulk_action(user, content_type, ACTION_BULK_DELETE, message) +@python_2_unicode_compatible class UserAction(models.Model): """ A record of an action (add, edit, or delete) performed on an object by a User. diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index c0ca2b0ad..d2bb3ce03 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -7,6 +7,7 @@ from django.core.urlresolvers import reverse from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.db.models.expressions import RawSQL +from django.utils.encoding import python_2_unicode_compatible from dcim.models import Interface from extras.models import CustomFieldModel, CustomFieldValue @@ -70,6 +71,7 @@ IP_PROTOCOL_CHOICES = ( ) +@python_2_unicode_compatible class VRF(CreatedUpdatedModel, CustomFieldModel): """ A virtual routing and forwarding (VRF) table represents a discrete layer three forwarding domain (e.g. a routing @@ -105,6 +107,7 @@ class VRF(CreatedUpdatedModel, CustomFieldModel): ]) +@python_2_unicode_compatible class RIR(models.Model): """ A Regional Internet Registry (RIR) is responsible for the allocation of a large portion of the global IP address @@ -127,6 +130,7 @@ class RIR(models.Model): return "{}?rir={}".format(reverse('ipam:aggregate_list'), self.slug) +@python_2_unicode_compatible class Aggregate(CreatedUpdatedModel, CustomFieldModel): """ An aggregate exists at the root level of the IP address space hierarchy in NetBox. Aggregates are used to organize @@ -204,6 +208,7 @@ class Aggregate(CreatedUpdatedModel, CustomFieldModel): return int(children_size / self.prefix.size * 100) +@python_2_unicode_compatible class Role(models.Model): """ A Role represents the functional role of a Prefix or VLAN; for example, "Customer," "Infrastructure," or @@ -263,6 +268,7 @@ class PrefixQuerySet(NullsFirstQuerySet): return filter(lambda p: p.depth <= limit, queryset) +@python_2_unicode_compatible class Prefix(CreatedUpdatedModel, CustomFieldModel): """ A Prefix represents an IPv4 or IPv6 network, including mask length. Prefixes can optionally be assigned to Sites and @@ -377,6 +383,7 @@ class IPAddressManager(models.Manager): return qs.annotate(host=RawSQL('INET(HOST(ipam_ipaddress.address))', [])).order_by('family', 'host') +@python_2_unicode_compatible class IPAddress(CreatedUpdatedModel, CustomFieldModel): """ An IPAddress represents an individual IPv4 or IPv6 address and its mask. The mask length should match what is @@ -469,6 +476,7 @@ class IPAddress(CreatedUpdatedModel, CustomFieldModel): return STATUS_CHOICE_CLASSES[self.status] +@python_2_unicode_compatible class VLANGroup(models.Model): """ A VLAN group is an arbitrary collection of VLANs within which VLAN IDs and names must be unique. @@ -493,6 +501,7 @@ class VLANGroup(models.Model): return "{}?group_id={}".format(reverse('ipam:vlan_list'), self.pk) +@python_2_unicode_compatible class VLAN(CreatedUpdatedModel, CustomFieldModel): """ A VLAN is a distinct layer two forwarding domain identified by a 12-bit integer (1-4094). Each VLAN must be assigned @@ -558,6 +567,7 @@ class VLAN(CreatedUpdatedModel, CustomFieldModel): return STATUS_CHOICE_CLASSES[self.status] +@python_2_unicode_compatible class Service(CreatedUpdatedModel): """ A Service represents a layer-four service (e.g. HTTP or SSH) running on a Device. A Service may optionally be tied diff --git a/netbox/secrets/models.py b/netbox/secrets/models.py index 052050927..a0c3e6f8b 100644 --- a/netbox/secrets/models.py +++ b/netbox/secrets/models.py @@ -8,7 +8,7 @@ from django.contrib.auth.models import Group, User from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse from django.db import models -from django.utils.encoding import force_bytes +from django.utils.encoding import force_bytes, python_2_unicode_compatible from dcim.models import Device from utilities.models import CreatedUpdatedModel @@ -51,6 +51,7 @@ class UserKeyQuerySet(models.QuerySet): raise Exception("Bulk deletion has been disabled.") +@python_2_unicode_compatible class UserKey(CreatedUpdatedModel): """ A UserKey stores a user's personal RSA (public) encryption key, which is used to generate their unique encrypted @@ -170,6 +171,7 @@ class UserKey(CreatedUpdatedModel): self.save() +@python_2_unicode_compatible class SecretRole(models.Model): """ A SecretRole represents an arbitrary functional classification of Secrets. For example, a user might define roles @@ -201,6 +203,7 @@ class SecretRole(models.Model): return user in self.users.all() or user.groups.filter(pk__in=self.groups.all()).exists() +@python_2_unicode_compatible class Secret(CreatedUpdatedModel): """ A Secret stores an AES256-encrypted copy of sensitive data, such as passwords or secret keys. An irreversible diff --git a/netbox/tenancy/models.py b/netbox/tenancy/models.py index c690ce7b7..df871fc31 100644 --- a/netbox/tenancy/models.py +++ b/netbox/tenancy/models.py @@ -1,12 +1,14 @@ from django.contrib.contenttypes.fields import GenericRelation from django.core.urlresolvers import reverse from django.db import models +from django.utils.encoding import python_2_unicode_compatible from extras.models import CustomFieldModel, CustomFieldValue from utilities.models import CreatedUpdatedModel from utilities.utils import csv_format +@python_2_unicode_compatible class TenantGroup(models.Model): """ An arbitrary collection of Tenants. @@ -24,6 +26,7 @@ class TenantGroup(models.Model): return "{}?group={}".format(reverse('tenancy:tenant_list'), self.slug) +@python_2_unicode_compatible class Tenant(CreatedUpdatedModel, CustomFieldModel): """ A Tenant represents an organization served by the NetBox owner. This is typically a customer or an internal