# Buggy code
def handle(self, *args, **options):
    current_page_id = None
    missing_models_content_type_ids = set()
    for revision in (
        PageRevision.objects.order_by("page_id", "created_at")
        .select_related("page")
        .iterator()
    ):
        # This revision is for a page type that is no longer in the database. Bail out early.
        if revision.page.content_type_id in missing_models_content_type_ids:
            continue
        if not revision.page.specific_class:
            missing_models_content_type_ids.add(revision.page.content_type_id)
            continue

        is_new_page = revision.page_id != current_page_id
        if is_new_page:
            # reset previous revision when encountering a new page.
            previous_revision = None

        has_content_changes = False
        current_page_id = revision.page_id

        if not PageLogEntry.objects.filter(revision=revision).exists():
            try:
                current_revision_as_page = revision.as_page_object()
            except Exception:
                # restoring old revisions may fail if e.g. they have an on_delete=PROTECT foreign key
                # to a no-longer-existing model instance. We cannot compare changes between two
                # non-restorable revisions, although we can at least infer that there was a content
                # change at the point that it went from restorable to non-restorable or vice versa.
                current_revision_as_page = None

            published = revision.id == revision.page.live_revision_id

            if previous_revision is not None:
                try:
                    previous_revision_as_page = previous_revision.as_page_object()
                except Exception:
                    previous_revision_as_page = None

                if (
                    previous_revision_as_page is None
                    and current_revision_as_page is None
                ):
                    # both revisions failed to restore - unable to determine presence of content changes
                    has_content_changes = False
                elif (
                    previous_revision_as_page is None
                    or current_revision_as_page is None
                ):
                    # one or the other revision failed to restore, which indicates a content change
                    has_content_changes = True
                else:
                    # Must use .specific so the comparison picks up all fields, not just base Page ones.
                    comparison = get_comparison(
                        revision.page.specific,
                        previous_revision_as_page,
                        current_revision_as_page,
                    )
                    has_content_changes = len(comparison) > 0

                if current_revision_as_page.live_revision_id == previous_revision.id:
                    # Log the previous revision publishing.
                    self.log_page_action("wagtail.publish", previous_revision, True)

            if is_new_page or has_content_changes or published:
                if is_new_page:
                    action = "wagtail.create"
                elif published:
                    action = "wagtail.publish"
                else:
                    action = "wagtail.edit"

                if published and has_content_changes:
                    # When publishing, also log the 'draft save', but only if there have been content changes
                    self.log_page_action("wagtail.edit", revision, has_content_changes)

                self.log_page_action(action, revision, has_content_changes)

        previous_revision = revision


# Traceback (AttributeError)
$ python manage.py create_log_entries_from_revisions

Traceback (most recent call last):
File "manage.py", line 12, in <module>
execute_from_command_line(sys.argv)
File "/lib/python3.6/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
utility.execute()
File "/lib/python3.6/site-packages/django/core/management/__init__.py", line 375, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/lib/python3.6/site-packages/django/core/management/base.py", line 323, in run_from_argv
self.execute(*args, **cmd_options)
File "/lib/python3.6/site-packages/django/core/management/base.py", line 364, in execute
output = self.handle(*args, **options)
File "/lib/python3.6/site-packages/wagtail/core/management/commands/create_log_entries_from_revisions.py", line 62, in handle
if current_revision_as_page.live_revision_id == previous_revision.id:
AttributeError: 'NoneType' object has no attribute 'live_revision_id'

# Fixed code
def handle(self, *args, **options):
    current_page_id = None
    missing_models_content_type_ids = set()
    for revision in (
        PageRevision.objects.order_by("page_id", "created_at")
        .select_related("page")
        .iterator()
    ):
        # This revision is for a page type that is no longer in the database. Bail out early.
        if revision.page.content_type_id in missing_models_content_type_ids:
            continue
        if not revision.page.specific_class:
            missing_models_content_type_ids.add(revision.page.content_type_id)
            continue

        is_new_page = revision.page_id != current_page_id
        if is_new_page:
            # reset previous revision when encountering a new page.
            previous_revision = None

        has_content_changes = False
        current_page_id = revision.page_id

        if not PageLogEntry.objects.filter(revision=revision).exists():
            try:
                current_revision_as_page = revision.as_page_object()
            except Exception:
                # restoring old revisions may fail if e.g. they have an on_delete=PROTECT foreign key
                # to a no-longer-existing model instance. We cannot compare changes between two
                # non-restorable revisions, although we can at least infer that there was a content
                # change at the point that it went from restorable to non-restorable or vice versa.
                current_revision_as_page = None

            published = revision.id == revision.page.live_revision_id

            if previous_revision is not None:
                try:
                    previous_revision_as_page = previous_revision.as_page_object()
                except Exception:
                    previous_revision_as_page = None

                if (
                    previous_revision_as_page is None
                    and current_revision_as_page is None
                ):
                    # both revisions failed to restore - unable to determine presence of content changes
                    has_content_changes = False
                elif (
                    previous_revision_as_page is None
                    or current_revision_as_page is None
                ):
                    # one or the other revision failed to restore, which indicates a content change
                    has_content_changes = True
                else:
                    # Must use .specific so the comparison picks up all fields, not just base Page ones.
                    comparison = get_comparison(
                        revision.page.specific,
                        previous_revision_as_page,
                        current_revision_as_page,
                    )
                    has_content_changes = len(comparison) > 0

                if (
                    current_revision_as_page is not None
                    and current_revision_as_page.live_revision_id
                    == previous_revision.id
                ):
                    # Log the previous revision publishing.
                    self.log_page_action("wagtail.publish", previous_revision, True)

            if is_new_page or has_content_changes or published:
                if is_new_page:
                    action = "wagtail.create"
                elif published:
                    action = "wagtail.publish"
                else:
                    action = "wagtail.edit"

                if published and has_content_changes:
                    # When publishing, also log the 'draft save', but only if there have been content changes
                    self.log_page_action("wagtail.edit", revision, has_content_changes)

                self.log_page_action(action, revision, has_content_changes)

        previous_revision = revision