docs: def publish(self):
          """
          Publishes the object.
  
          The decorator `assert_draft` makes sure that you cannot publish
          a published object.
          :param self: The object to tbe published.
          :return: The published object.
          """
          if self.is_draft:
              # If the object has previously been linked then patch the
              # placeholder data and remove the previously linked object.
              # Otherwise set the published date.
              if self.publishing_linked:
                  self.patch_placeholders()
                  # Unlink draft and published copies then delete published.
                  # NOTE: This indirect dance is necessary to avoid
                  # triggering unwanted MPTT tree structure updates via
                  # `save`.
                  type(self.publishing_linked).objects \
                      .filter(pk=self.publishing_linked.pk) \
                      .delete()  # Instead of self.publishing_linked.delete()
              else:
                  self.publishing_published_at = timezone.now()
  
              # Create a new object copying all fields.
              publish_obj = deepcopy(self)
  
              # If any fields are defined not to copy set them to None.
              for fld in self.publishing_publish_empty_fields + (
                  'urlnode_ptr_id', 'publishing_linked_id'
              ):
                  setattr(publish_obj, fld, None)
  
              # Set the state of publication to published on the object.
              publish_obj.publishing_is_draft = False
  
              # Update Fluent's publishing status field mechanism to correspond
              # to our own notion of publication, to help use work together more
              # easily with Fluent Pages.
              if isinstance(self, UrlNode):
                  self.status = UrlNode.DRAFT
                  publish_obj.status = UrlNode.PUBLISHED
  
              # Set the date the object should be published at.
              publish_obj.publishing_published_at = self.publishing_published_at
  
              # Perform per-model preparation before saving published copy
              publish_obj.publishing_prepare_published_copy(self)
  
              # Save the new published object as a separate instance to self.
              publish_obj.save()
              # Sanity-check that we successfully saved the published copy
              if not publish_obj.pk:  # pragma: no cover
                  raise PublishingException("Failed to save published copy")
  
              # As it is a new object we need to clone each of the
              # translatable fields, placeholders and required relations.
              self.clone_parler_translations(publish_obj)
              self.clone_fluent_placeholders_and_content_items(publish_obj)
              self.clone_fluent_contentitems_m2m_relationships(publish_obj)
  
              # Extra relationship-cloning smarts
              publish_obj.publishing_clone_relations(self)
  
              # Link the published object to the draft object.
              self.publishing_linked = publish_obj
  
              # Flag draft instance when it is being updated as part of a
              # publish action, for use in `publishing_set_update_time`
              self._skip_update_publishing_modified_at = True
  
              # Signal the pre-save hook for publication, save then signal
              # the post publish hook.
              publishing_signals.publishing_publish_pre_save_draft.send(
                  sender=type(self), instance=self)
  
              # Save the draft and its new relationship with the published copy
              publishing_signals.publishing_publish_save_draft.send(
                  sender=type(self), instance=self)
  
              publishing_signals.publishing_post_publish.send(
                  sender=type(self), instance=self)
              return publish_obj