def METHOD_NAME(apps, schema_editor):
    Person = apps.get_model("people", "Person")
    PersonIdentifier = apps.get_model("people", "PersonIdentifier")
    ContentType = apps.get_model("contenttypes", "ContentType")
    ComplexPopoloField = apps.get_model("candidates", "ComplexPopoloField")
    person_ct = ContentType.objects.get_for_model(Person).pk
    # The ComplexPopoloField model stores "name" and "info_type" for each field
    # we care about. The "note" field on e.g. the Link model stores the value
    # of "info_type", but we want to convert that to using "name", so we'll
    # make a mapping here.
    # The reason for this is that the "note" /"info_type" value is something
    # like `party candidate page` whereas the "name" is a python-var-safe
    # `party_ppc_page_url`.
    cpf_info_type_to_name = {
        cpf.info_type: cpf.name for cpf in ComplexPopoloField.objects.all()
    }
    # Add this manually as the value was changed in the past
    cpf_info_type_to_name["party PPC page"] = "party_ppc_page_url"
    # Models we want to move
    Link = apps.get_model("popolo", "Link")
    ContactDetail = apps.get_model("popolo", "ContactDetail")
    Identifier = apps.get_model("popolo", "Identifier")
    # Links
    # We can't simply copy the links over as there is a new unique constraint
    # on (person, value) that didn't exist on popolo.Link.
    # In the live data there are over 300 people with duplicate links
    # This method will only copy one of them. No link data will be lost,
    # but it's possible that the wrong `value_type` will be selected.
    # This is something that a human needs to look at, and not something we're
    # making worse by removing a duplicate. A list of all the problem values
    # can be made before running this migration.
    qs = Link.objects.filter(content_type=person_ct)
    links_by_person = {}
    links_to_move = []
    for link in qs:
        person_id = link.object_id
        if person_id not in links_by_person:
            links_by_person[person_id] = set()
        if link.url in links_by_person[person_id]:
            # Ignore this link if we've seen it for this person before
            # and assume the previous `value_type` is ok to use (it won't
            # always be)
            continue
        links_by_person[person_id].add(link.url)
        links_to_move.append(
            PersonIdentifier(
                value=link.url,
                person_id=link.object_id,
                value_type=cpf_info_type_to_name[link.note],
            )
        )
    PersonIdentifier.objects.bulk_create(links_to_move)
    # Contact Detail
    # Exclude contact_type="TWITTER" (upper case) as there is some old data
    # with this value that's duplicated in contact_type="twitter" (lower case)
    # We can safely delete this data. (4 rows at the time of writing)
    # AFIK "TWITTER" was a legacy from some older version of YNR/Popit
    qs = ContactDetail.objects.filter(content_type=person_ct).exclude(
        contact_type="TWITTER"
    )
    contact_detail_to_move = []
    for contact_detail in qs:
        contact_detail_to_move.append(
            PersonIdentifier(
                value=contact_detail.value,
                person_id=contact_detail.object_id,
                value_type=cpf_info_type_to_name[contact_detail.contact_type],
            )
        )
    PersonIdentifier.objects.bulk_create(contact_detail_to_move)
    # Twitter IDs
    # This is a special case. We're storing Twitter IDs in one model,
    # and Twitter usernames in another. The below will merge the two
    # but make an assumption that only one Twitter ID exists per person
    # (This is the case with all the current live data)
    qs = Identifier.objects.filter(scheme="twitter")
    for popolo_identifier in qs:
        try:
            pi = PersonIdentifier.objects.get(
                person_id=popolo_identifier.object_id,
                value_type="twitter_username",
            )
        except PersonIdentifier.DoesNotExist:
            continue
        pi.internal_identifier = popolo_identifier.identifier
        pi.save()