pandas+Django 以數據流的方式 導出 複雜數據(問卷調研) 快速

導出樣式:

表設計:

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("暫無數據可導出")

 


 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章