导出样式:
表设计:
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("暂无数据可导出")