pandas+Django 以数据流的方式 导出 复杂数据(问卷调研) 快速

导出样式:

pandas+Django 以数据流的方式 导出 复杂数据(问卷调研) 快速_第1张图片

表设计:

class QuestionnaireTB(models.Model):
    """问卷管理"""""
    survey_type = models.ManyToManyField('SurveyType', verbose_name='问卷分类')
    title=models.CharField('问卷标题',max_length=100)
    describe=models.TextField('问卷描述')
    questions=models.ManyToManyField('QuestionBank',verbose_name='问卷题')
    sort=models.IntegerField('排序',default=0,help_text='越大越靠前')
    is_show=models.BooleanField('展示',default=False)
    create_time=models.DateTimeField('创建时间',auto_now_add=True)
    def __unicode__(self):
        return self.title
    class Meta:
        verbose_name='问卷管理'
        verbose_name_plural=verbose_name



QUESTION_TYPE=((1, u'单选题'), (2, u'多选题'), (3, u'主观题'))
class QuestionBank(models.Model):
    """题库管理"""""
    title = models.CharField(u'题名', max_length=255)
    question = models.IntegerField(u'题的类别', choices=QUESTION_TYPE, default=1)
    add_time = models.DateTimeField(u'添加时间', auto_now_add=True)

    def __unicode__(self):
        return '%s--%s'%(self.get_question_display(),self.title)

    class Meta:
        verbose_name = '题库管理'
        verbose_name_plural = verbose_name



class Select(models.Model):
    """选项管理"""""
    questionbank = models.ForeignKey('QuestionBank', verbose_name='对应到题')
    sele_con = models.CharField(u'选项', max_length=255)

    def __unicode__(self):
        return self.sele_con
    class Meta:
        verbose_name='选项管理'
        verbose_name_plural=verbose_name


class AnswerRecord(models.Model):
    """答题管理"""""
    patient=models.ForeignKey('PatientTB',verbose_name='答题人')
    question=models.ForeignKey('QuestionnaireTB',verbose_name='答得问卷')
    create_time=models.DateTimeField('答题时间',auto_now_add=True)
    def __unicode__(self):
        return self.name
    class Meta:
        verbose_name='答题管理'
        verbose_name_plural=verbose_name


class StudyQuestRecord(models.Model):
    """答题详情"""""
    viewing = models.ForeignKey('AnswerRecord', verbose_name='对应总的')
    answer_topic = models.ForeignKey('QuestionBank', verbose_name='对应到题', blank=True, null=True)
    da_an = models.TextField(u'回答', blank=True)

    def __unicode__(self):
        return self.da_an

    class Meta:
        verbose_name = '答题详情记录'
        verbose_name_plural = verbose_name

导出思路:主要难点在与 将每一道题放在用户信息后面,根据pandas的pandas.merge( db1,db2,on='') 来将DataFrame后的数据进行合并,还需要将对应的回到放到 对应的标题下

代码如下:

     

from io import BytesIO
import pandas as pd
from django.http import HttpResponse
def QuestExcel(req):
    id=req.GET.get('id')
    quest=QuestionnaireTB.objects.get(id=id)
    answer=AnswerRecord.objects.filter(question_id=id)
    if answer:
        outfile = BytesIO()
        username = u'问卷答题记录'
        product = pd.DataFrame(answer.values('patient_id','question__title'))
        dataer=[]
        answers = StudyQuestRecord.objects.filter(viewing__question_id=id)
        two_list = []
        for que in quest.questions.all().values_list('title',flat=True): #这个是拿到所有题的标题
            two_list.append(que)
            anser_list = list(answers.filter(answer_topic__title=que).annotate(patient_id=F('viewing__patient_id')).values("patient_id", "da_an")) #这里是为了在合并时字段 好处理  使用annotate将字段重命名
            ans = pd.DataFrame(anser_list)
            ans.rename(columns={'da_an': que}, inplace=True) #因为结构化的数据是以字段没列名的  这里需要修改列名
            dataer.append(ans)
        df2 = dataer[0]
        if len(two_list) > 1:
            for ab in dataer[1:]:
                df2 = pd.merge(df2, ab, on="patient_id")
        ordersers = pd.merge(product, df2, on="patient_id")
        response = HttpResponse(content_type='application/vnd.ms-excel')
        execl_name = '%sorderexcel%s' % (username, datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S'))
        response['Content-Disposition'] = 'attachment;filename={0}.xlsx'.format(execl_name)
        ordersers.to_excel(outfile, index=False)
        response.write(outfile.getvalue())
        return response
    return HttpResponse("暂无数据可导出")

 

 

你可能感兴趣的:(pandas,Django,excel)