old_contents: from django.utils import timezone
  from django.db import models
  
  from framework.utils import iso8601format
  from website.util import sanitize
  
  from osf_models.models.base import BaseModel, ObjectIDMixin
  
  class PrivateLink(ObjectIDMixin, BaseModel):
      date_created = models.DateTimeField(default=timezone.now)
      key = models.CharField(max_length=512, null=False, unique=True, blank=False)
      name = models.CharField(max_length=255)
      is_deleted = models.BooleanField(default=False)
      anonymous = models.BooleanField(default=False)
  
      nodes = models.ManyToManyField('Node', related_name='private_links')
      creator = models.ForeignKey('OSFUser', null=True, blank=True, on_delete=models.SET_NULL)
  
      @property
      def node_ids(self):
          # TODO: do this the django way
          node_ids = [node._id for node in self.nodes]
          return node_ids
  
      def node_scale(self, node):
          # node may be None if previous node's parent is deleted
          if node is None or node.parent_id not in self.node_ids:
              return -40
          else:
              offset = 20 if node.parent_node is not None else 0
              return offset + self.node_scale(node.parent_node)
  
      def to_json(self):
          return {
              'id': self._id,
              'date_created': iso8601format(self.date_created),
              'key': self.key,
              'name': sanitize.unescape_entities(self.name),
              'creator': {'fullname': self.creator.fullname, 'url': self.creator.profile_url},
              'nodes': [{'title': x.title, 'url': x.url,
                         'scale': str(self.node_scale(x)) + 'px', 'category': x.category}
                        for x in self.nodes if not x.is_deleted],
              'anonymous': self.anonymous
          }
  
new_contents: from django.utils import timezone
  from django.db import models
  
  from framework.utils import iso8601format
  from website.util import sanitize
  
  from osf_models.models.base import BaseModel, ObjectIDMixin
  
  class PrivateLink(ObjectIDMixin, BaseModel):
      date_created = models.DateTimeField(default=timezone.now)
      key = models.CharField(max_length=512, null=False, unique=True, blank=False)
      name = models.CharField(max_length=255)
      is_deleted = models.BooleanField(default=False)
      anonymous = models.BooleanField(default=False)
  
      nodes = models.ManyToManyField('Node', related_name='private_links')
      creator = models.ForeignKey('OSFUser', null=True, blank=True, on_delete=models.SET_NULL)
  
      @property
      def node_ids(self):
          return self.nodes.values_list('_guid__guid', flat=True)
  
      def node_scale(self, node):
          # node may be None if previous node's parent is deleted
          if node is None or node.parent_id not in self.node_ids:
              return -40
          else:
              offset = 20 if node.parent_node is not None else 0
              return offset + self.node_scale(node.parent_node)
  
      def to_json(self):
          return {
              'id': self._id,
              'date_created': iso8601format(self.date_created),
              'key': self.key,
              'name': sanitize.unescape_entities(self.name),
              'creator': {'fullname': self.creator.fullname, 'url': self.creator.profile_url},
              'nodes': [{'title': x.title, 'url': x.url,
                         'scale': str(self.node_scale(x)) + 'px', 'category': x.category}
                        for x in self.nodes if not x.is_deleted],
              'anonymous': self.anonymous
          }
  
subject: Refactor PrivateLink.node_ids to use values_list