Example #1
0
def import_we_vote_positions_from_json(request, load_from_uri=False):
    """
    Get the json data, and either create new entries or update existing
    :return:
    """
    if load_from_uri:
        # Request json file from We Vote servers
        messages.add_message(request, messages.INFO, "Loading positions from We Vote Master servers")
        request = requests.get(POSITIONS_URL, params={
            "key": WE_VOTE_API_KEY,  # This comes from an environment variable
        })
        structured_json = json.loads(request.text)
    else:
        # Load saved json from local file
        messages.add_message(request, messages.INFO, "Loading positions from local file")

        with open(POSITIONS_JSON_FILE) as json_data:
            structured_json = json.load(json_data)

    for one_position in structured_json:
        # Make sure we have the minimum required variables
        if len(one_position["id_we_vote"]) == 0 \
                or len(one_position["organization_id_we_vote"]) == 0\
                or len(one_position["candidate_campaign_id_we_vote"]) == 0:
            continue

        # Check to see if this position is already being used anywhere
        position_on_stage_found = False
        try:
            if len(one_position["id_we_vote"]) > 0:
                position_query = PositionEntered.objects.filter(id_we_vote=one_position["id_we_vote"])
                if len(position_query):
                    position_on_stage = position_query[0]
                    position_on_stage_found = True
        except PositionEntered.DoesNotExist as e:
            handle_exception_silently(e)
        except Exception as e:
            handle_record_not_found_exception(e)

        # We need to look up the local organization_id based on the newly saved we_vote_id
        organization_manager = OrganizationManager()
        organization_id = organization_manager.fetch_organization_id(one_position["organization_id_we_vote"])

        # We need to look up the local candidate_campaign_id
        candidate_campaign_manager = CandidateCampaignManager()
        candidate_campaign_id = candidate_campaign_manager.fetch_candidate_campaign_id_from_id_we_vote(
            one_position["candidate_campaign_id_we_vote"])

        # TODO We need to look up measure_campaign_id
        measure_campaign_id = 0

        try:
            if position_on_stage_found:
                # Update
                position_on_stage.id_we_vote = one_position["id_we_vote"]
                position_on_stage.organization_id = organization_id
                position_on_stage.candidate_campaign_id = candidate_campaign_id
                position_on_stage.measure_campaign_id = measure_campaign_id
                position_on_stage.date_entered = one_position["date_entered"]
                position_on_stage.election_id = one_position["election_id"]
                position_on_stage.stance = one_position["stance"]
                position_on_stage.more_info_url = one_position["more_info_url"]
                position_on_stage.statement_text = one_position["statement_text"]
                position_on_stage.statement_html = one_position["statement_html"]
                position_on_stage.save()
                messages.add_message(request, messages.INFO, "Position updated: {id_we_vote}".format(
                    id_we_vote=one_position["id_we_vote"]))
            else:
                # Create new
                position_on_stage = PositionEntered(
                    id_we_vote=one_position["id_we_vote"],
                    organization_id=organization_id,
                    candidate_campaign_id=candidate_campaign_id,
                    measure_campaign_id=measure_campaign_id,
                    date_entered=one_position["date_entered"],
                    election_id=one_position["election_id"],
                    stance=one_position["stance"],
                    more_info_url=one_position["more_info_url"],
                    statement_text=one_position["statement_text"],
                    statement_html=one_position["statement_html"],
                )
                position_on_stage.save()
                messages.add_message(request, messages.INFO, "New position imported: {id_we_vote}".format(
                    id_we_vote=one_position["id_we_vote"]))
        except Exception as e:
            handle_record_not_saved_exception(e)
            messages.add_message(request, messages.ERROR,
                                 "Could not save position, id_we_vote: {id_we_vote}, "
                                 "organization_id_we_vote: {organization_id_we_vote}, "
                                 "candidate_campaign_id_we_vote: {candidate_campaign_id_we_vote}".format(
                                     id_we_vote=one_position["id_we_vote"],
                                     organization_id_we_vote=one_position["organization_id_we_vote"],
                                     candidate_campaign_id_we_vote=one_position["candidate_campaign_id_we_vote"],
                                 ))
Example #2
0
def assemble_candidate_campaign_stance_html(candidate_campaign_id,
                                            stance_we_are_looking_for,
                                            positions_followed,
                                            positions_not_followed):
    """

    :param all_positions_list_for_candidate_campaign:
    :param stance_we_are_looking_for:
    :param candidate_campaign_id:
    :return:
    """
    #################################
    # Start with positions_followed

    # Assemble some information that is independent of each position
    number_of_positions_followed_total = len(positions_followed)
    popup_box_title_verb = display_stance_we_are_looking_for_title(
        stance_we_are_looking_for, number_of_positions_followed_total)

    candidate_campaign_manager = CandidateCampaignManager()
    results = candidate_campaign_manager.retrieve_candidate_campaign_from_id(
        candidate_campaign_id)
    if results['candidate_campaign_found']:
        candidate_campaign = results['candidate_campaign']
        popup_box_title_candidate_name = candidate_campaign.candidate_name
    else:
        popup_box_title_candidate_name = ""

    popup_box_title = popup_box_title_verb + " " + popup_box_title_candidate_name
    if stance_we_are_looking_for == SUPPORT:
        # This is the class we reference with jquery for opening a div popup to display the supporters
        class_used_to_open_popup = "candidate_campaign_" + candidate_campaign_id + "_supporters"
        # This is the URL that returns the supporters for this candidate
        retrieve_positions_url = "/pos/cand/" + candidate_campaign_id + "/supporters?f=1"  # Only show orgs followed
    elif stance_we_are_looking_for == OPPOSE:
        class_used_to_open_popup = "candidate_campaign_" + candidate_campaign_id + "_opposers"
        retrieve_positions_url = "/pos/cand/" + candidate_campaign_id + "/opposers?f=1"
    elif stance_we_are_looking_for == INFORMATION_ONLY:
        class_used_to_open_popup = "candidate_campaign_" + candidate_campaign_id + "_infoonly"
        retrieve_positions_url = "/pos/cand/" + candidate_campaign_id + "/infoonlylist?f=1"
    elif stance_we_are_looking_for == STILL_DECIDING:
        class_used_to_open_popup = "candidate_campaign_" + candidate_campaign_id + "_deciders"
        retrieve_positions_url = "/pos/cand/" + candidate_campaign_id + "/deciders?f=1"
    else:
        class_used_to_open_popup = ''
        retrieve_positions_url = ''

    # Cycle through these positions and put together a line about who is supporting, opposing, have information
    #  or are still deciding
    positions_followed_stance_html = ""
    is_first = True
    number_of_positions_followed_counter = 0
    only_you = False
    for position in positions_followed:
        if is_first:
            positions_followed_stance_html += ""
        else:
            is_next_to_last = number_of_positions_followed_counter == number_of_positions_followed_total - 1
            positions_followed_stance_html += " and " if is_next_to_last else ", "
        is_first = False

        if position.organization_id > 0:
            organization_manager = OrganizationManager()
            results = organization_manager.retrieve_organization(
                position.organization_id)
            if results['organization_found']:
                organization_on_stage = results['organization']
                link_open = "<a class='{link_class}' href='{link_href}' id='{popup_box_title}'>".format(
                    link_class=class_used_to_open_popup,
                    link_href=retrieve_positions_url,
                    popup_box_title=popup_box_title,
                )
                positions_followed_stance_html += "{link_open}{organization_name}</a>".format(
                    link_open=link_open,
                    organization_name=organization_on_stage.name,
                )
                number_of_positions_followed_counter += 1
        elif position.voter_id > 0:
            positions_followed_stance_html += "You"
            number_of_positions_followed_counter += 1
            if number_of_positions_followed_total == 1:
                only_you = True
    if number_of_positions_followed_total:
        verb_text = display_stance_we_are_looking_for(
            stance_we_are_looking_for, number_of_positions_followed_total,
            only_you)
        if verb_text:
            positions_followed_stance_html = "<span class='positions_followed_text'>" + positions_followed_stance_html
            positions_followed_stance_html += " <span class='position_stance_verb'>{verb_text}</span>".format(
                verb_text=verb_text)
            positions_followed_stance_html += "</span>"

    #################################
    # NOT Followed
    #################################
    # Now create string with html for positions_not_followed
    positions_not_followed_stance_html = ""
    number_of_positions_not_followed_total = len(positions_not_followed)
    # If there aren't any "not followed" positions, just return the positions_followed_stance_html
    if number_of_positions_not_followed_total == 0:
        return positions_followed_stance_html
    else:
        only_you = False

    # If here we know there is at least one position available that isnt' being followed by voter
    popup_box_title = popup_box_title_verb + " " + popup_box_title_candidate_name
    if stance_we_are_looking_for == SUPPORT:
        # This is the class we reference with jquery for opening a div popup to display the supporters
        class_used_to_open_popup = "candidate_campaign_" + candidate_campaign_id + "_supporters"
        # This is the URL that returns the supporters for this candidate
        retrieve_positions_url = "/pos/cand/" + candidate_campaign_id + "/supporters?nf=1"  # Only show orgs not followed
    elif stance_we_are_looking_for == OPPOSE:
        class_used_to_open_popup = "candidate_campaign_" + candidate_campaign_id + "_opposers"
        retrieve_positions_url = "/pos/cand/" + candidate_campaign_id + "/opposers?nf=1"
    elif stance_we_are_looking_for == INFORMATION_ONLY:
        class_used_to_open_popup = "candidate_campaign_" + candidate_campaign_id + "_infoonly"
        retrieve_positions_url = "/pos/cand/" + candidate_campaign_id + "/infoonlylist?nf=1"
    elif stance_we_are_looking_for == STILL_DECIDING:
        class_used_to_open_popup = "candidate_campaign_" + candidate_campaign_id + "_deciders"
        retrieve_positions_url = "/pos/cand/" + candidate_campaign_id + "/deciders?nf=1"
    else:
        class_used_to_open_popup = ''
        retrieve_positions_url = ''

    link_open = "<a class='{link_class}' href='{link_href}' id='{popup_box_title}'>".format(
        link_class=class_used_to_open_popup,
        link_href=retrieve_positions_url,
        popup_box_title=popup_box_title,
    )

    # How we display the link to the positions NOT followed varies based on the number of *followed* positions
    if number_of_positions_followed_total == 0:
        if number_of_positions_not_followed_total == 1:
            not_followed_stance_verb = display_stance_verb_we_are_looking_for_singular(
                stance_we_are_looking_for)
        else:
            not_followed_stance_verb = display_stance_verb_we_are_looking_for_plural(
                stance_we_are_looking_for)
        positions_not_followed_stance_html += \
            "{link_open}{number} {not_followed_stance_verb}</a> ({link_open}learn more</a>)".format(
                link_open=link_open,
                number=number_of_positions_not_followed_total,
                not_followed_stance_verb=not_followed_stance_verb,
            )
    elif number_of_positions_followed_total < 5:
        if number_of_positions_not_followed_total == 1:
            not_followed_stance_verb = "other " + display_stance_verb_we_are_looking_for_plural(
                stance_we_are_looking_for)
        else:
            not_followed_stance_verb = "others " + display_stance_verb_we_are_looking_for_singular(
                stance_we_are_looking_for)
        positions_not_followed_stance_html += \
            "({link_open}{number_of_positions_not_followed_total} {not_followed_stance_verb}</a>)".format(
                link_open=link_open,
                number_of_positions_not_followed_total=number_of_positions_not_followed_total,
                not_followed_stance_verb=not_followed_stance_verb,
            )
    else:  # When there are more than 5 positions from followed organizations
        positions_not_followed_stance_html += "({link_open}show more supporters</a>)".format(
            link_open=link_open, )

    stance_html = positions_followed_stance_html + " " + "<span class='positions_not_followed'>" + positions_not_followed_stance_html + "</span>"

    return stance_html
Example #3
0
def import_we_vote_positions_from_json(request, load_from_uri=False):
    """
    Get the json data, and either create new entries or update existing
    :return:
    """
    if load_from_uri:
        # Request json file from We Vote servers
        messages.add_message(request, messages.INFO,
                             "Loading positions from We Vote Master servers")
        request = requests.get(
            POSITIONS_URL,
            params={
                "key":
                WE_VOTE_API_KEY,  # This comes from an environment variable
            })
        structured_json = json.loads(request.text)
    else:
        # Load saved json from local file
        messages.add_message(request, messages.INFO,
                             "Loading positions from local file")

        with open(POSITIONS_JSON_FILE) as json_data:
            structured_json = json.load(json_data)

    for one_position in structured_json:
        # Make sure we have the minimum required variables
        if len(one_position["id_we_vote"]) == 0 \
                or len(one_position["organization_id_we_vote"]) == 0\
                or len(one_position["candidate_campaign_id_we_vote"]) == 0:
            continue

        # Check to see if this position is already being used anywhere
        position_on_stage_found = False
        try:
            if len(one_position["id_we_vote"]) > 0:
                position_query = PositionEntered.objects.filter(
                    id_we_vote=one_position["id_we_vote"])
                if len(position_query):
                    position_on_stage = position_query[0]
                    position_on_stage_found = True
        except PositionEntered.DoesNotExist as e:
            pass
        except Exception as e:
            handle_record_not_found_exception(e, logger=logger)

        # We need to look up the local organization_id based on the newly saved we_vote_id
        organization_manager = OrganizationManager()
        organization_id = organization_manager.fetch_organization_id(
            one_position["organization_id_we_vote"])

        # We need to look up the local candidate_campaign_id
        candidate_campaign_manager = CandidateCampaignManager()
        candidate_campaign_id = candidate_campaign_manager.fetch_candidate_campaign_id_from_id_we_vote(
            one_position["candidate_campaign_id_we_vote"])

        # TODO We need to look up measure_campaign_id
        measure_campaign_id = 0

        try:
            if position_on_stage_found:
                # Update
                position_on_stage.id_we_vote = one_position["id_we_vote"]
                position_on_stage.organization_id = organization_id
                position_on_stage.candidate_campaign_id = candidate_campaign_id
                position_on_stage.measure_campaign_id = measure_campaign_id
                position_on_stage.date_entered = one_position["date_entered"]
                position_on_stage.election_id = one_position["election_id"]
                position_on_stage.stance = one_position["stance"]
                position_on_stage.more_info_url = one_position["more_info_url"]
                position_on_stage.statement_text = one_position[
                    "statement_text"]
                position_on_stage.statement_html = one_position[
                    "statement_html"]
                position_on_stage.save()
                messages.add_message(
                    request, messages.INFO,
                    u"Position updated: {id_we_vote}".format(
                        id_we_vote=one_position["id_we_vote"]))
            else:
                # Create new
                position_on_stage = PositionEntered(
                    id_we_vote=one_position["id_we_vote"],
                    organization_id=organization_id,
                    candidate_campaign_id=candidate_campaign_id,
                    measure_campaign_id=measure_campaign_id,
                    date_entered=one_position["date_entered"],
                    election_id=one_position["election_id"],
                    stance=one_position["stance"],
                    more_info_url=one_position["more_info_url"],
                    statement_text=one_position["statement_text"],
                    statement_html=one_position["statement_html"],
                )
                position_on_stage.save()
                messages.add_message(
                    request, messages.INFO,
                    u"New position imported: {id_we_vote}".format(
                        id_we_vote=one_position["id_we_vote"]))
        except Exception as e:
            handle_record_not_saved_exception(e, logger=logger)
            messages.add_message(
                request, messages.ERROR,
                u"Could not save position, id_we_vote: {id_we_vote}, "
                u"organization_id_we_vote: {organization_id_we_vote}, "
                u"candidate_campaign_id_we_vote: {candidate_campaign_id_we_vote}"
                .format(
                    id_we_vote=one_position["id_we_vote"],
                    organization_id_we_vote=one_position[
                        "organization_id_we_vote"],
                    candidate_campaign_id_we_vote=one_position[
                        "candidate_campaign_id_we_vote"],
                ))
Example #4
0
def transfer_maplight_data_to_we_vote_tables(request):
    # TODO We need to perhaps set up a table for these mappings that volunteers can add to?
    #  We need a plan for how volunteers can help us add to these mappings
    # One possibility -- ask volunteers to update this Google Sheet, then write a csv importer:
    #  https://docs.google.com/spreadsheets/d/1havD7GCxmBhi-zLLMdOpSJlU_DtBjvb5IJNiXgno9Bk/edit#gid=0
    politician_name_mapping_list = []
    one_mapping = {
        "google_civic_name": "Betty T. Yee",
        "maplight_display_name": "Betty Yee",
        "maplight_original_name": "Betty T Yee",
    }
    politician_name_mapping_list.append(one_mapping)
    one_mapping = {
        "google_civic_name": "Edmund G. \"Jerry\" Brown",
        "maplight_display_name": "Jerry Brown",
        "maplight_original_name": "",
    }
    politician_name_mapping_list.append(one_mapping)

    candidate_campaign_manager = CandidateCampaignManager()

    maplight_candidates_current_query = MapLightCandidate.objects.all()

    for one_candidate_from_maplight_table in maplight_candidates_current_query:
        found_by_id = False
        # Try to find a matching candidate
        results = candidate_campaign_manager.retrieve_candidate_campaign_from_id_maplight(
            one_candidate_from_maplight_table.candidate_id)

        if not results['success']:
            logger.warn(u"Candidate NOT found by MapLight id: {name}".format(
                name=one_candidate_from_maplight_table.candidate_id
            ))
            results = candidate_campaign_manager.retrieve_candidate_campaign_from_candidate_name(
                one_candidate_from_maplight_table.display_name)

            if not results['success']:
                logger.warn(u"Candidate NOT found by display_name: {name}".format(
                    name=one_candidate_from_maplight_table.display_name
                ))
                results = candidate_campaign_manager.retrieve_candidate_campaign_from_candidate_name(
                    one_candidate_from_maplight_table.original_name)

                if not results['success']:
                    logger.warn(u"Candidate NOT found by original_name: {name}".format(
                        name=one_candidate_from_maplight_table.original_name
                    ))

                    one_mapping_google_civic_name = ''
                    for one_mapping_found in politician_name_mapping_list:
                        if value_exists(one_mapping_found['maplight_display_name']) \
                                and one_mapping_found['maplight_display_name'] == \
                                one_candidate_from_maplight_table.display_name:
                            one_mapping_google_civic_name = one_mapping_found['google_civic_name']
                            break
                    if value_exists(one_mapping_google_civic_name):
                        results = candidate_campaign_manager.retrieve_candidate_campaign_from_candidate_name(
                            one_mapping_google_civic_name)
                    if not results['success'] or not value_exists(one_mapping_google_civic_name):
                        logger.warn(u"Candidate NOT found by mapping to google_civic name: {name}".format(
                            name=one_mapping_google_civic_name
                        ))

                        continue  # Go to the next candidate

        candidate_campaign_on_stage = results['candidate_campaign']

        # Just in case the logic above let us through to here accidentally without a candidate_name value, don't proceed
        if not value_exists(candidate_campaign_on_stage.candidate_name):
            continue

        logger.debug(u"Candidate {name} found".format(
            name=candidate_campaign_on_stage.candidate_name
        ))

        try:
            # Tie the maplight id to our record
            if not found_by_id:
                candidate_campaign_on_stage.id_maplight = one_candidate_from_maplight_table.candidate_id

            # Bring over the photo
            candidate_campaign_on_stage.photo_url_from_maplight = one_candidate_from_maplight_table.photo

            # We can bring over other data as needed, like gender for example
            candidate_campaign_on_stage.save()
        except Exception as e:
            handle_record_not_saved_exception(e, logger=logger)

    messages.add_message(request, messages.INFO, 'MapLight data woven into We Vote tables.')

    return HttpResponseRedirect(reverse('import_export:import_export_index', args=()))
Example #5
0
def transfer_maplight_data_to_we_vote_tables(request):
    # TODO We need to perhaps set up a table for these mappings that volunteers can add to?
    #  We need a plan for how volunteers can help us add to these mappings
    # One possibility -- ask volunteers to update this Google Sheet, then write a csv importer:
    #  https://docs.google.com/spreadsheets/d/1havD7GCxmBhi-zLLMdOpSJlU_DtBjvb5IJNiXgno9Bk/edit#gid=0
    politician_name_mapping_list = []
    one_mapping = {
        "google_civic_name": "Betty T. Yee",
        "maplight_display_name": "Betty Yee",
        "maplight_original_name": "Betty T Yee",
    }
    politician_name_mapping_list.append(one_mapping)
    one_mapping = {
        "google_civic_name": "Edmund G. \"Jerry\" Brown",
        "maplight_display_name": "Jerry Brown",
        "maplight_original_name": "",
    }
    politician_name_mapping_list.append(one_mapping)

    candidate_campaign_manager = CandidateCampaignManager()

    maplight_candidates_current_query = MapLightCandidate.objects.all()

    for one_candidate_from_maplight_table in maplight_candidates_current_query:
        found_by_id = False
        # Try to find a matching candidate
        results = candidate_campaign_manager.retrieve_candidate_campaign_from_id_maplight(
            one_candidate_from_maplight_table.candidate_id)

        if not results['success']:
            logger.warn(u"Candidate NOT found by MapLight id: {name}".format(
                name=one_candidate_from_maplight_table.candidate_id))
            results = candidate_campaign_manager.retrieve_candidate_campaign_from_candidate_name(
                one_candidate_from_maplight_table.display_name)

            if not results['success']:
                logger.warn(
                    u"Candidate NOT found by display_name: {name}".format(
                        name=one_candidate_from_maplight_table.display_name))
                results = candidate_campaign_manager.retrieve_candidate_campaign_from_candidate_name(
                    one_candidate_from_maplight_table.original_name)

                if not results['success']:
                    logger.warn(
                        u"Candidate NOT found by original_name: {name}".format(
                            name=one_candidate_from_maplight_table.
                            original_name))

                    one_mapping_google_civic_name = ''
                    for one_mapping_found in politician_name_mapping_list:
                        if value_exists(one_mapping_found['maplight_display_name']) \
                                and one_mapping_found['maplight_display_name'] == \
                                one_candidate_from_maplight_table.display_name:
                            one_mapping_google_civic_name = one_mapping_found[
                                'google_civic_name']
                            break
                    if value_exists(one_mapping_google_civic_name):
                        results = candidate_campaign_manager.retrieve_candidate_campaign_from_candidate_name(
                            one_mapping_google_civic_name)
                    if not results['success'] or not value_exists(
                            one_mapping_google_civic_name):
                        logger.warn(
                            u"Candidate NOT found by mapping to google_civic name: {name}"
                            .format(name=one_mapping_google_civic_name))

                        continue  # Go to the next candidate

        candidate_campaign_on_stage = results['candidate_campaign']

        # Just in case the logic above let us through to here accidentally without a candidate_name value, don't proceed
        if not value_exists(candidate_campaign_on_stage.candidate_name):
            continue

        logger.debug(u"Candidate {name} found".format(
            name=candidate_campaign_on_stage.candidate_name))

        try:
            # Tie the maplight id to our record
            if not found_by_id:
                candidate_campaign_on_stage.id_maplight = one_candidate_from_maplight_table.candidate_id

            # Bring over the photo
            candidate_campaign_on_stage.photo_url_from_maplight = one_candidate_from_maplight_table.photo

            # We can bring over other data as needed, like gender for example
            candidate_campaign_on_stage.save()
        except Exception as e:
            handle_record_not_saved_exception(e, logger=logger)

    messages.add_message(request, messages.INFO,
                         'MapLight data woven into We Vote tables.')

    return HttpResponseRedirect(
        reverse('import_export:import_export_index', args=()))
Example #6
0
def assemble_candidate_campaign_stance_html(
        candidate_campaign_id, stance_we_are_looking_for, positions_followed, positions_not_followed):
    """

    :param all_positions_list_for_candidate_campaign:
    :param stance_we_are_looking_for:
    :param candidate_campaign_id:
    :return:
    """
    #################################
    # Start with positions_followed

    # Assemble some information that is independent of each position
    number_of_positions_followed_total = len(positions_followed)
    popup_box_title_verb = display_stance_we_are_looking_for_title(
        stance_we_are_looking_for, number_of_positions_followed_total)

    candidate_campaign_manager = CandidateCampaignManager()
    results = candidate_campaign_manager.retrieve_candidate_campaign_from_id(candidate_campaign_id)
    if results['candidate_campaign_found']:
        candidate_campaign = results['candidate_campaign']
        popup_box_title_candidate_name = candidate_campaign.candidate_name
    else:
        popup_box_title_candidate_name = ""

    popup_box_title = popup_box_title_verb+" "+popup_box_title_candidate_name
    if stance_we_are_looking_for == SUPPORT:
        # This is the class we reference with jquery for opening a div popup to display the supporters
        class_used_to_open_popup = "candidate_campaign_"+candidate_campaign_id+"_supporters"
        # This is the URL that returns the supporters for this candidate
        retrieve_positions_url = "/pos/cand/"+candidate_campaign_id+"/supporters?f=1"  # Only show orgs followed
    elif stance_we_are_looking_for == OPPOSE:
        class_used_to_open_popup = "candidate_campaign_"+candidate_campaign_id+"_opposers"
        retrieve_positions_url = "/pos/cand/"+candidate_campaign_id+"/opposers?f=1"
    elif stance_we_are_looking_for == INFORMATION_ONLY:
        class_used_to_open_popup = "candidate_campaign_"+candidate_campaign_id+"_infoonly"
        retrieve_positions_url = "/pos/cand/"+candidate_campaign_id+"/infoonlylist?f=1"
    elif stance_we_are_looking_for == STILL_DECIDING:
        class_used_to_open_popup = "candidate_campaign_"+candidate_campaign_id+"_deciders"
        retrieve_positions_url = "/pos/cand/"+candidate_campaign_id+"/deciders?f=1"
    else:
        class_used_to_open_popup = ''
        retrieve_positions_url = ''

    # Cycle through these positions and put together a line about who is supporting, opposing, have information
    #  or are still deciding
    positions_followed_stance_html = ""
    is_first = True
    number_of_positions_followed_counter = 0
    only_you = False
    for position in positions_followed:
        if is_first:
            positions_followed_stance_html += ""
        else:
            is_next_to_last = number_of_positions_followed_counter == number_of_positions_followed_total - 1
            positions_followed_stance_html += " and " if is_next_to_last else ", "
        is_first = False

        if position.organization_id > 0:
            organization_manager = OrganizationManager()
            results = organization_manager.retrieve_organization(position.organization_id)
            if results['organization_found']:
                organization_on_stage = results['organization']
                link_open = "<a class='{link_class}' href='{link_href}' id='{popup_box_title}'>".format(
                    link_class=class_used_to_open_popup,
                    link_href=retrieve_positions_url,
                    popup_box_title=popup_box_title,
                )
                positions_followed_stance_html += "{link_open}{organization_name}</a>".format(
                    link_open=link_open,
                    organization_name=organization_on_stage.name,
                )
                number_of_positions_followed_counter += 1
        elif position.voter_id > 0:
            positions_followed_stance_html += "You"
            number_of_positions_followed_counter += 1
            if number_of_positions_followed_total == 1:
                only_you = True
    if number_of_positions_followed_total:
        verb_text = display_stance_we_are_looking_for(
            stance_we_are_looking_for, number_of_positions_followed_total, only_you)
        if verb_text:
            positions_followed_stance_html = "<span class='positions_followed_text'>" + positions_followed_stance_html
            positions_followed_stance_html += " <span class='position_stance_verb'>{verb_text}</span>".format(verb_text=verb_text)
            positions_followed_stance_html += "</span>"

    #################################
    # NOT Followed
    #################################
    # Now create string with html for positions_not_followed
    positions_not_followed_stance_html = ""
    number_of_positions_not_followed_total = len(positions_not_followed)
    # If there aren't any "not followed" positions, just return the positions_followed_stance_html
    if number_of_positions_not_followed_total == 0:
        return positions_followed_stance_html
    else:
        only_you = False

    # If here we know there is at least one position available that isnt' being followed by voter
    popup_box_title = popup_box_title_verb+" "+popup_box_title_candidate_name
    if stance_we_are_looking_for == SUPPORT:
        # This is the class we reference with jquery for opening a div popup to display the supporters
        class_used_to_open_popup = "candidate_campaign_"+candidate_campaign_id+"_supporters"
        # This is the URL that returns the supporters for this candidate
        retrieve_positions_url = "/pos/cand/"+candidate_campaign_id+"/supporters?nf=1"  # Only show orgs not followed
    elif stance_we_are_looking_for == OPPOSE:
        class_used_to_open_popup = "candidate_campaign_"+candidate_campaign_id+"_opposers"
        retrieve_positions_url = "/pos/cand/"+candidate_campaign_id+"/opposers?nf=1"
    elif stance_we_are_looking_for == INFORMATION_ONLY:
        class_used_to_open_popup = "candidate_campaign_"+candidate_campaign_id+"_infoonly"
        retrieve_positions_url = "/pos/cand/"+candidate_campaign_id+"/infoonlylist?nf=1"
    elif stance_we_are_looking_for == STILL_DECIDING:
        class_used_to_open_popup = "candidate_campaign_"+candidate_campaign_id+"_deciders"
        retrieve_positions_url = "/pos/cand/"+candidate_campaign_id+"/deciders?nf=1"
    else:
        class_used_to_open_popup = ''
        retrieve_positions_url = ''

    link_open = "<a class='{link_class}' href='{link_href}' id='{popup_box_title}'>".format(
        link_class=class_used_to_open_popup,
        link_href=retrieve_positions_url,
        popup_box_title=popup_box_title,
    )

    # How we display the link to the positions NOT followed varies based on the number of *followed* positions
    if number_of_positions_followed_total == 0:
        if number_of_positions_not_followed_total == 1:
            not_followed_stance_verb = display_stance_verb_we_are_looking_for_singular(stance_we_are_looking_for)
        else:
            not_followed_stance_verb = display_stance_verb_we_are_looking_for_plural(stance_we_are_looking_for)
        positions_not_followed_stance_html += \
            "{link_open}{number} {not_followed_stance_verb}</a> ({link_open}learn more</a>)".format(
                link_open=link_open,
                number=number_of_positions_not_followed_total,
                not_followed_stance_verb=not_followed_stance_verb,
            )
    elif number_of_positions_followed_total < 5:
        if number_of_positions_not_followed_total == 1:
            not_followed_stance_verb = "other "+display_stance_verb_we_are_looking_for_plural(stance_we_are_looking_for)
        else:
            not_followed_stance_verb = "others "+display_stance_verb_we_are_looking_for_singular(stance_we_are_looking_for)
        positions_not_followed_stance_html += \
            "({link_open}{number_of_positions_not_followed_total} {not_followed_stance_verb}</a>)".format(
                link_open=link_open,
                number_of_positions_not_followed_total=number_of_positions_not_followed_total,
                not_followed_stance_verb=not_followed_stance_verb,
            )
    else:  # When there are more than 5 positions from followed organizations
        positions_not_followed_stance_html += "({link_open}show more supporters</a>)".format(
            link_open=link_open,
        )

    stance_html = positions_followed_stance_html + " " + "<span class='positions_not_followed'>" + positions_not_followed_stance_html + "</span>"

    return stance_html