導出樣式:
表設計:
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("暫無數據可導出")