@staticmethod
    @task
    def index2plan(name, body, filename, owner=None, template=False, purge=False, email=None, language=None):
        prev_lang = None
        if not language is None:
            prev_lang = get_language()
            activate(language)

        if email:
            error_subject = _("Problem importing your uploaded file.")
            success_subject = _("Upload and import plan confirmation.")
            admin_subject = _("Problem importing user uploaded file.")
            
            context = DjangoContext({
                'user': owner,
                'errors': list()
            })
        
        # Is this filename a zip archive?
        if filename.endswith('.zip'):
            try:
                archive = zipfile.ZipFile(filename,'r')

                # Does the zip file contain more than one entry?
                if len(archive.namelist()) > 1:
                    archive.close()
                    if purge:
                        os.unlink(filename)

                    if email:
                        context['errors'].append({'message': _('The zip file contains too many files'), 'traceback': None})
                        # report error to owner
                        email_template = loader.get_template('error.email')
                        send_mail(error_subject, email_template.render(context), settings.EMAIL_HOST_USER, [email], fail_silently=False)
                        # report error to admin
                        email_template = loader.get_template('admin.email')
                        mail_admins(admin_subject, email_template.render(context))
                    else:
                        logger.warn('District Index .zip file contains too many files.')

                    # reset translation to default
                    if not prev_lang is None:
                        activate(prev_lang)

                    return

                item = archive.namelist()[0]
                # Does the first entry in the zipfile end in ".csv"?
                if not item.endswith('.csv'):
                    archive.close()
                    if purge:
                        os.unlink(filename)

                    if email:
                        context['errors'].append({'message': _('The zip file must contain a comma separated value (.csv) file.'), 'traceback': None})

                        # report error to owner
                        email_template = loader.get_template('error.email')
                        send_mail(error_subject, email_template.render(context), settings.EMAIL_HOST_USER, [email], fail_silently=False)
                        # report error to admin
                        email_template = loader.get_template('admin.email')
                        mail_admins(admin_subject, email_template.render(context))
                    else:
                        logger.warn('District Index .zip file does not contain a .csv file.\n')

                    # reset translation to default
                    if not prev_lang is None:
                        activate(prev_lang)

                    return

                # Now extract entry
                dest = tempfile.NamedTemporaryFile(mode='w+b+', delete=False)

                # Open the item in the archive
                indexItem = archive.open(item)
                for line in indexItem:
                    # Write the archive data to the filesystem
                    dest.write(line)
                # Close the item in the archive
                indexItem.close()
                # Close the filesystem (extracted) item
                dest.close()
                # Close the archive
                archive.close()

                if purge:
                    try:
                        os.unlink(filename)
                    except:
                        logger.info('Could not unlink file: "%s"', filename)

                indexFile = dest.name

            except Exception, ex:
                if email:
                    context['errors'].append({'message': _('Unexpected error during zip file processing'), 'traceback': traceback.format_exc()}) 
                    # report error to owner
                    email_template = loader.get_template('error.email')
                    send_mail(error_subject, email_template.render(context), settings.EMAIL_HOST_USER, [email], fail_silently=False)
                    # report error to admin
                    email_template = loader.get_template('admin.email')
                    mail_admins(admin_subject, email_template.render(context))
                else:
                    logger.info('The .zip file could not be imported')
                    logger.debug('Reason:', ex)

                if purge:
                    # Some problem opening the zip file, bail now
                    os.unlink(filename)

                # reset translation to default
                if not prev_lang is None:
                    activate(prev_lang)

                return
       
        else: # filename.endswith('.csv'):
            indexFile = filename

            if not os.path.exists(indexFile):
                logger.warn('The .csv file could not be found, plan "%s" was not created.', name)
                return

        legislative_body = LegislativeBody.objects.get(id=int(body))
        
        plan = Plan.create_default(name, legislative_body, owner=owner, template=template, processing_state=ProcessingState.CREATING, create_unassigned=False)

        if not plan:
            if email:
                context['errors'].append({'message': _("Plan couldn't be created. Be sure the plan name is unique."), 'tracback': None })
                template = loader.get_template('error.email')
                send_mail(error_subject, template.render(context), settings.EMAIL_HOST_USER, [email], fail_silently=False)
                template = loader.get_template('admin.email')
                mail_admins(error_subject, template.render(context))
            else:
                logger.warn('The plan "%s" could not be created', name)

            # reset translation to default
            if not prev_lang is None:
                activate(prev_lang)

            return
                
        # initialize the dicts we'll use to store the portable_ids,
        # keyed on the district_id of this plan
        new_districts = dict()
        num_members = dict()
        community_labels = dict()
        community_types = dict()
        community_comments = dict()
        csv_file = open(indexFile)
        reader = csv.DictReader(csv_file, fieldnames = ['code', 'district', 'num_members', 'label', 'types', 'comments'])
        for row in reader:
            try:
                dist_id = int(row['district'])
                # If the district key is present, add this row's code; 
                # else make a new list
                if dist_id in new_districts:
                    new_districts[dist_id].append(str(row['code']))
                else:
                    new_districts[dist_id] = list()
                    new_districts[dist_id].append(str(row['code']))

                    # num_members may not exist in files exported before the column was added
                    num_members[dist_id] = int(row['num_members']) if row['num_members'] else 1

                    # community components are only present on community plans
                    if row['label']:
                        community_labels[dist_id] = row['label']
                    if row['types']:
                        community_types[dist_id] = row['types']
                    if row['comments']:
                        community_comments[dist_id] = row['comments']
                    
            except Exception, ex:
                if email:
                    context['errors'].append({
                        'message': '%s\n  "%s, %s"\n' % (_('Did not import row:'), row['code'], row['district']),
                        'traceback': traceback.format_exc()
                    })
                else:
                    logger.debug("Did not import row: '%s'", row)
                    logger.debug(ex)

        csv_file.close()

        if purge:
            os.unlink(indexFile)
        # Get all subjects - those without denominators first to save a calculation
        subjects = Subject.objects.order_by('-percentage_denominator').all()

        # Determine if this is a community plan
        is_community = bool(community_labels)
        ct = ContentType.objects.get(app_label='redistricting',model='district')        

        # Create the district geometry from the lists of geounits
        for district_id in new_districts.keys():
            # Get a filter using portable_id
            code_list = new_districts[district_id]
            guFilter = Q(portable_id__in = code_list)

            try:
                # Build our new geometry from the union of our geounit geometries
                new_geom = Geounit.objects.filter(guFilter).unionagg()
                
                # Create a new district and save it
                short_label = community_labels[district_id][:10] if is_community else legislative_body.get_short_label() % {'district_id':district_id }
                long_label = community_labels[district_id][:256] if is_community else legislative_body.get_label() % {'district_id':district_id}
                new_district = District(short_label=short_label,long_label=long_label,
                    district_id = district_id, plan=plan, num_members=num_members[district_id],
                    geom=enforce_multi(new_geom))
                new_district.simplify() # implicit save

                # Add community fields if this is a community plan
                if is_community:
                    # Add comments
                    if district_id in community_comments:
                        comments_str = community_comments[district_id]
                    if comments_str:
                        comment = Comment(object_pk=new_district.id, content_type=ct, site_id=1, user_name=owner, user_email=email, comment=comments_str)
                        comment.save()

                    # Add types
                    if district_id in community_types:
                        types_str = community_types[district_id]
                    if types_str:
                        for strtag in types_str.split('|'):
                            if strtag:
                                Tag.objects.add_tag(new_district, 'type=%s' % strtag)
                
            except Exception, ex:
                if email:
                    context['errors'].append({
                        'message': '%s %s' % (_('Unable to create district'), district_id),
                        'traceback': traceback.format_exc()
                    })
                else:
                    logger.warn('Unable to create district %s.', district_id)
                    logger.debug('Reason:', ex)
                continue
        
            # For each district, create the ComputedCharacteristics
            geounit_ids = Geounit.objects.filter(guFilter).values_list('id', flat=True).order_by('id')
            for subject in subjects:
                try:
                    cc_value = Characteristic.objects.filter(
                        geounit__in = geounit_ids, 
                        subject = subject).aggregate(Sum('number'))
                    value = cc_value['number__sum']
                    percentage = '0000.00000000'

                    if value is not None:
                        if subject.percentage_denominator:
                            # The denominator's CC should've already been saved
                            denominator_value = ComputedCharacteristic.objects.get(
                                subject = subject.percentage_denominator,
                                district = new_district).number
                            percentage = value / denominator_value

                        cc = ComputedCharacteristic(subject = subject, 
                            number = value, 
                            percentage = percentage,
                            district = new_district)
                        cc.save()
                    else:
                        logger.debug('Unable to create ComputedCharacteristic for Subject: %s. Skipping subject.', subject.name)
                        continue
                except Exception, ex:
                    if email:
                        context['errors'].append({
                            'message': _('Unable to create ComputedCharacteristic for district %(district_id)s, subject %(subject_name)s') % {'district':district_id, 'subject_name':subject.name},
                            'traceback': None
                        })
                    else:
                        logger.debug('Unable to create ComputedCharacteristic for district %s, subject %s', district_id, subject.name)
                        logger.debug('Reason:', ex)

        # Now that all of our other districts exist, create an unassigned district
        plan.create_unassigned = True
        create_unassigned_district(plan, instance=plan, created=True)
        # this plan is complete, and no longer creating
        plan.processing_state = ProcessingState.READY
        plan.save()

        if email:
            context['plan'] = plan
            # Plan operations completed successfully. It's unclear if the
            # accumulated messages are problems or not. Let's assume they are.

            if len(context['errors']) > 0:
                template = loader.get_template('admin.email')
                mail_admins(admin_subject, template.render(context))

            template = loader.get_template('importedplan.email')
            send_mail(success_subject, template.render(context), settings.EMAIL_HOST_USER, [email], fail_silently=False)

        # reset translation back to default
        if not prev_lang is None:
            activate(prev_lang)
Should redirect to the setting for the default site.
dataset/ETHPy150Open PublicMapping/DistrictBuilder/django/publicmapping/redistricting/tasks.py/DistrictIndexFile.index2plan--crossover with--dataset/ETHPy150Open torchbox/wagtail/wagtail/contrib/settings/tests/test_admin.py/TestMultiSite.test_redirect_to_default